Java集合干货系列-(五)HashSet源码解析
前言
今天来介绍下HashSet。前面,我们已经系统的对List和Map进行了学习。接下来,我们开始可以学习Set。相信经过Map的了解之后,学习Set会容易很多。毕竟,Set的实现类都是基于Map来实现的(HashSet是通过HashMap实现的)。
构造图如下:
蓝色线条:继承
绿色线条:接口实现
正文
对于HashSet而言,它是基于HashMap来实现的,底层采用HashMap来保存元素。所以如果对HashMap比较熟悉,那么HashSet是so easy!!
HashSet简介
HashSet定义
1
|
public class HashSet<E>
|
HashSet 是一个没有重复元素的集合。
它是由HashMap实现的,不保证元素的顺序,而且HashSet允许使用 null 元素。
HashSet是非同步的。如果多个线程同时访问一个哈希 set,而其中至少一个线程修改了该 set,那么它必须 保持外部同步。这通常是通过对自然封装该 set 的对象执行同步操作来完成的。如果不存在这样的对象,则应该使用 Collections.synchronizedSet 方法来“包装” set。最好在创建时完成这一操作,以防止对该 set 进行意外的不同步访问:
1
|
Set s = Collections.synchronizedSet(new HashSet(...));
|
HashSet通过iterator()返回的迭代器是fail-fast的。
HashSet属性
1
|
// 底层使用HashMap来保存HashSet的元素
|
看到这里就明白了,和我们前面说的一样,HashSet是用HashMap来保存数据,而主要使用到的就是HashMap的key。
看到private static final Object PRESENT = new Object();不知道你有没有一点疑问呢。这里使用一个静态的常量Object类来充当HashMap的value,既然这里map的value是没有意义的,为什么不直接使用null值来充当value呢?比如写成这样子private final Object PRESENT = null;我们都知道的是,Java首先将变量PRESENT分配在栈空间,而将new出来的Object分配到堆空间,这里的new Object()是占用堆内存的(一个空的Object对象占用8byte),而null值我们知道,是不会在堆空间分配内存的。那么想一想这里为什么不使用null值。想到什么吗,看一个异常类java.lang.NullPointerException, 噢买尬,这绝对是Java程序员的一个噩梦,这是所有Java程序猿都会遇到的一个异常,你看到这个异常你以为很好解决,但是有些时候也不是那么容易解决,Java号称没有指针,但是处处碰到NullPointerException。所以啊,为了从根源上避免NullPointerException的出现,浪费8个byte又怎么样,在下面的代码中我再也不会写这样的代码啦if (xxx == null) { … } else {….},好爽。
HashSet构造函数
1
|
/**
|
从构造方法可以很轻松的看出,HashSet的底层是一个HashMap,理解了HashMap后,这里没什么可说的。只有最后一个构造方法有写区别,这里构造的是LinkedHashMap,该方法不对外公开,实际上是提供给LinkedHashSet使用的,而第三个参数dummy是无意义的,只是为了区分其他构造方法。
API方法摘要
HashSet源码解析(基于JDK1.6.0_45)
增加和删除
1
|
/**
|
是否包含
1
|
/**
|
由于HashMap基于hash表实现,hash表实现的容器最重要的一点就是可以快速存取,那么HashSet对于contains方法,利用HashMap的containsKey方法,效率是非常之快的。在我看来,这个方法也是HashSet最核心的卖点方法之一。
容量检查
1
|
/**
|
HashSet遍历方式
通过Iterator遍历HashSet
第一步:根据iterator()获取HashSet的迭代器。
第二步:遍历迭代器获取各个元素。
1
|
// 假设set是HashSet对象
|
通过for-each遍历HashSet
第一步:根据toArray()获取HashSet的元素集合对应的数组。
第二步:遍历数组,获取各个元素。
1
|
// 假设set是HashSet对象,并且set中元素是String类型
|
HashSet示例
下面我们通过实例学习如何使用HashSet
1
|
import java.util.Iterator;
|
运行结果:
1
|
size : 5
|
总结
HashSet和HashMap、Hashtable的区别
参考
该文为本人学习的笔记,方便以后自己跳槽前复习。参考网上各大帖子,取其精华整合自己的理解而成。集合框架源码面试经常会问,所以解读源码十分必要,希望对你有用。
java提高篇(二四)—–HashSet
Java 集合系列16之 HashSet详细介绍(源码解析)和使用示例
给jdk写注释系列之jdk1.6容器(6)-HashSet源码解析&Map迭代器
整理的集合框架思维导图
个人整理的Java集合框架思维导图,动态维护。导出的图片无法查看备注的一些信息,所以需要源文件的童鞋可以关注我个人主页上的公众号,回复Java集合框架即可获取源文件。
博主弄了个java学习资源的公众号,学习资源超级多,视频,电子书,最新开发工具一个都不能少,已全部分享到百度云盘,求资源共享,打造一个学习方便,工作方便的java公众号,开源开源,有需求的可以关注~撒花



浙公网安备 33010602011771号