Java之HashSet的底层原理:面试常问考点
- HashSet 在很多面试中都是一个高频的考点。那么我们看看HashSet面试都问什么?
-
面试官常问你HashSet的底层数据结构是什么? HashMap ,这个 时候面试官又问HashMap 怎么能对呢? HashMap 是<k,v >的数据结构啊,而HashSet 是一个v的数据结构啊,这个时候面试官会说我觉得你对源码了解的不多。但是其实顶层就是HashMap的数据结构,用HashMap的key去保存Set中的值,而HashMap中的V是一个Object对象常量 (如下图中的源码)。这个时候面试官又会问哪为什么用Object 对象呢?用Null不是更好嘛?
image.png -
接下来我们就分析分析为什么使用Object 对象而不是用Null。这也要看源码了,这和remove(Object o)方法有关。因为我们知道HashSet底层使用的是HashMap,所有remove也是调用HashMap方法的,我们既然要使用remove方法,我们也看到了boolean 这个返回值,这就要求我们需要返回一个boolean值,那么如果我们设置的值不是Object 对象而是Null的话,使用remove方法移除那个值就判断不出来到底删除成功还是没有成功了。所以不能使用Null。
image.png
-
- 如果你仔细看源码里面的方法,你会发现很多方法都是调用HashMap中的方法(详细请看Java之HashMap的底层原理:面试常考知识点
) 。如下等等。
image.png
image.png -
其实HashSet就是低配版本的HashMap,这就是为什么HashMap 这么重要的一个原因。当我们看LinkedHashMap源码的时候发现底层就是HashSet,那么HashSet底层是LinkedHashMap,那么大胆的猜测一下LinkedHashMap是不是HashMap.没错我们猜对了。
image.png
image.png
image.png-
同HashSet相比并没有实现新的功能(新的方法),只不过把HashSet中预留的构造方法启用了,因而可以实现有序插入,而这个具体的实现要去看LinkedHashMap了,我们使用时是不需要再可以去设置参数的,直接拿来用就行了。
image.png
image.png - 看上面accessOrder = false;这个是给构造器的一个参数,告诉构造器使用插入的顺序。
-
- 线程安全的Set
- Collections.synchronizedSet(new HashSet());
- new CopyOnWriteArraySet<>(); 写时复制技术的线程安全类详细参考Java之ArrayList的底层原理:面试常考考点中有讲解写时复制是如何保证性能安全而且还效率比较高。
- 总结
- HashSet、LinkHashSet、TreeSet的迭代遍历顺序是怎样的呢?
- Set是没有get()方法的,是通过map的iterator迭代器遍历的。
- LinkHashSet迭代顺序也是按照插入顺序遍历的,底层是有一个变量accessOrder = false,这是给HashSet迭代器的一个参数,才使它也是根据插入顺序迭代顺序输出的。
- TreeSet中存放的元素是有序的(不是插入时的顺序,是有按关键字大小排序的),且元素不能重复。而如何实现有序存储,就需要有一个比较器,其实说起来,TreeSet更受关注的是不重复且有序,这个有序就需要有一个compare的过程,因此会需要参数实现Comparable接口。
- 如果想彻底了解底层到底是如何思想那就需要看看我写的Java之HashMap的底层原理:面试常考知识点了
- HashSet、LinkHashSet、TreeSet的迭代遍历顺序是怎样的呢?