HashSet 、LinkedHashSet 源码级详解

简介: HashSet 、LinkedHashSet 源码级详解

Set 集合类体系如下:

HashSet -- 无序、不重复、无索引

LinkedHashSet -- 有序、不重复、无索引

TreeSet -- 可排序、不重复、无索引

HashSet

HashSet 底层采用 哈希表 存储数据

哈希表组成

JDK8 之前  -- 数组 + 链表

JDK8 之后  -- 数组 + 链表 +红黑树

一开始会把元素存储在数组中,但是哈希表会出现同一个索引位置要存储多个元素的情况,因此要将同一个索引位置的多个对象用链表或红黑树进行存储

哈希表的核心 -- 哈希值

哈希值我们可以理解为对象的整数形式

因为在哈希表存储的时候,不是从索引零开始按序存储的,而是根据公式

int index = (数组长度 - 1 )& 哈希值

index就是对象存储的位置

对象可以根据 hashCode 方法计算出哈希值,该方法定义在Object类中,因此所有对象都可调用,默认使用地址值进行计算,但是一般情况下用对象的地址值计算哈希值的意义不大,因此一般情况下会重写 hashCode 方法,利用对象内部属性计算哈希值

关于 hashCode 方法 重写,最重要的是 hashCode 方法和 equals 方法的联系,可以参考以下博客

我们对 对象相等 的定义是:当两个对象 equals 返回 true 时,则两个对象就是相同的

但是当两个对象不相等时,可能会得到相同的哈希值

哈希表存储的原理:

通过哈希值计算出存储的位置,如果该位置为null,则直接存入;

如果不为null,则调用equals方法(不为null说明多个对象的哈希值相等,但是哈希值相等不代表元素相等,元素是否相等的标准由equals判断),如果该位置存在equals为true的元素,则不存储,如果没有则存储(以链表或红黑树的形式存储)

所以从上面看出,哈希值具有两个作用,一是计算出存储位置,二是初步判断哈希表中是否存在相同元素


正是因为哈希表具有不存储相同对象的特点,HashSet才能做到不重复


又因为哈希表是数组+链表+红黑树,并且不是从索引0开始按序存储,所以HashSet是无序的、无索引的


如下图,在遍历的时候,会先查看0索引位置,没有元素,那么查看1索引位置,遍历该链表,继续查看2索引位置... 以此类推,因此遍历的结果是 黄 -> 橙 -> .. -> 深蓝 -> 浅蓝 ,而我们存储的顺序可能是 橙 -> 浅蓝 -> ... -> 蓝->黄

LinkedHashSet

本质上跟 HashSet 相同,只不过多了个双链表的机制记录储存的顺序

现在我们要将这四个元素存入哈希表中

现在存入第一个元素,此时还有一条双向链表,双向链表的头结点指向该元素

存入第二个元素,此时,第一个元素会记录下第二个元素的地址值,第二个元素也会记录第一个元素的地址值,这就形成了一个双向链表


存入第三个元素,第三个元素和第四个元素间同样会相互记录地址值

存入第四个元素

接下来要遍历的时候,不再和HashSet相同,而是直接从头节点开始遍历该双向链表,最后得到的结果就是有序的

目录
相关文章
|
8月前
|
Java uml
|
存储 缓存 安全
Java集合框架(Map篇)
在这个示例代码中,首先定义了一个数组和一个集合,并使用Arrays.asList()方法将数组转换成集合。接着对数组和集合分别进行排序,使用binarySearch()方法查找元素位置,使用copyOf()和copy()方法复制数组和集合,最后输出结果。可以看到,Arrays和Collections提供的方法可以方便地对数组和集合进行操作,节省开发者的时间和精力。
|
3月前
|
算法 Java 程序员
Map - TreeSet & TreeMap 源码解析
Map - TreeSet & TreeMap 源码解析
57 0
|
5月前
|
Java 程序员 C语言
赶快收藏!全网最佳Set集合详解:HashSet、TreeSet!
面试官:那TreeSet要怎么定制排序?TreeSet的自定义排序我们要利用Comparator接口,通过向TreeSet传入自定义排序规则的Comparator来实现。官方源码是这么解释的,南友们看一看。// 构造一个新的空树集,根据指定的比较器进行排序。// 插入到集合中的所有元素都必须能够通过指定的比较器相互比较: comparator. compare(e1, e2)不得对集合中的任何元素e1和e2抛出ClassCastException。
赶快收藏!全网最佳Set集合详解:HashSet、TreeSet!
|
8月前
|
设计模式
LinkedHashSet源码详解
LinkedHashSet源码详解
|
存储 安全 Java
Java集合Map之HashMap常用操作
在我看来 , 链表是为了解决hash碰撞使用的一种方法 : 拉线法 , 而红黑树是为了解决"拉的这个线"(链表存储的元素太多)过长的话元素遍历慢的问题
70 2
|
8月前
|
存储 安全 Java
Java集合篇之set,面试官:请说一说HashSet、LinkedHashSet、TreeSet的区别?
Java集合篇之set,面试官:请说一说HashSet、LinkedHashSet、TreeSet的区别?
53 0
|
8月前
|
存储 Java 索引
Java集合框架:ArrayList和LinkedList的区别是什么?
Java集合框架:ArrayList和LinkedList的区别是什么?
74 0
|
存储 对象存储
HashSet、TreeSet、LinkedHashSet的区别
HashSet、TreeSet、LinkedHashSet的区别
102 0
|
存储 算法
TreeSet 和 HashSet 的区别
TreeSet 和 HashSet 的区别
65 0