HashSet底层存储

java.util.HashSet 属于单列集合(Collection是单列集合类的根接口),特点是元素无序,而且不可重复。HashSet底层的实现其实是一个HashMap,是根据对象的哈希值来确定元素在集合中的存储位置,因此具有良好的存取和查找性能。

在JDK1.8之前,哈希表底层采用数组+链表实现,即使用链表处理冲突,同一hash值的链表都存储在一个链表里。 但是当位于一个桶中的元素较多,即hash值相等的元素较多时,通过key值依次查找的效率较低。而JDK1.8中,哈希表存储采用数组+链表+红黑树实现。

HashSet是如何保证存储元素的唯一性呢?这依赖于内部的hashCode 与 equals 方法

当插入一个元素时,首先调用对象的hashCode方法计算插入的数组索引,如果该位置为空,便直接插入。

那么问题来了,仅使用hashCode方法能否保证元素的不可重复?这引出了哈希冲突的概念,哈希冲突是指哈希函数算出来的地址被别的元素占用了,即具有一样的哈希值,例子如下:

System.out.println("ABCDEa123abc".hashCode());  // 165374702
System.out.println("ABCDFB123abc".hashCode()); //  165374702

两个不同的字符串调用hashcode得到的哈希值却是一样的。在HashMap中为了解决哈希冲突,采用了链地址法,当发生冲突的时候,它会在哈希函数找到的当前数组内存地址位置下添加一条链表,开始遍历链表进行插入,当链表长度超过阈值(8)时,将链表转换为红黑树,减少了遍历和查表的时间,增加了效率。在用拉链法构造的散列表中,删除结点的操作易于实现。只要简单地删去链表上相应的结点即可。

tips:如果想要存储的元素有序,那么需要使用LinkedHashSet进行存储,在hashset的基础上增加了一条记录节点的链,保证的存取元素的有序性。

发布了5 篇原创文章 · 获赞 0 · 访问量 275

猜你喜欢

转载自blog.csdn.net/niguang0908/article/details/104874530
今日推荐