Set集合的特点
无序:存取顺序不一致如存入张三、李四、王五。而遍历获取到的是李四, 张三, 王五
不重复:可以去除重复
无索引:没有带索引的方法,所以不能使用普通for循环遍历,也不能通过索引来获取元素
set集合的实现类
HashSet:无序、不重复、无索引LinkedHashSet:有序、不重复、无索引
TreeSet:可排序、不重复、无索引
hashset
HashSet 集合底层采取哈希表存储数据哈希表是一种对于增删改查数据 性能都较好的结构
哈希值:对象的整数表现形式
它是根据hashCode方法算出来的int类型的整数
该方法定义在Object类中,所有对象都可以调用,没有重写则默认使用地址值进行计算
一般情况下,会重写hashCode方法,利用对象内部的属性值计算哈希值
jdk8 及以后的 HashSet 的底层原理。
![](/i/l/?n=24&i=blog/3374466/202404/3374466-20240409100346024-996863832.png)
创建 HashSet 集合后,会在底层创建一个长度为 16 的数组 table,并加载 负载因子为0.75 的 HashMap
这意味着当 HashSet 中的元素数量达到数组长度的 75% 时,数组会进行扩容(原有长度*2)操作,以保持较低的碰撞率和良好的性能。
判断当前位置是否为 null,如果是 null 直接存入
如果不是 null,表示有元素,则调用 equals 方法比较属性值
一样则不存,不一样则存入,形成链表
注意: jdk8 以前:新元素存入数组,老元素挂在新元素下面,jdk8及以后:新元素直接挂在老元素下面。如图:
注意:当链表长度大于 8 并且 数组长度 大于等于 64 时,链表会变成红黑树。如图:![]
(/i/l/?n=24&i=blog/3374466/202404/3374466-20240409100452744-1394440810.png)
注意点:
如果集合中存储的是自定义对象 ,必须要重写 hashCode 和 equals 方法(有的类已经重写过了,如 String Integer,会自动去重)不然 操作的都是地址值(一般来说,我们对于地址值是没有需求的)。
重写 hashCode 是为了通过属性值计算哈希值
重写 equals 是为了比较对象内部属性