一、HashSet示例
1.以Set接口的实现类HashSet来讲解Set接口的方法
2.Set接口的实现类的对象(Set接口对象),不能存放重复的元素,可以添加一个null
3.Set接口对象存放数据是无序的(即添加的顺序和取出的顺序不一致)
4.注意:取出的顺序虽然不是添加的顺序,但是他是固定的
5. set接口对象,不能通过索引来获取。
二、HashSet全面说明
1.HashSet实现了Set接口
2.HashSet实际上是HashMap
3.可以存放null值,但是,只能有一个null
4.HashSet不保证元素是有序的,取决于Hash后,再确定索引的结果。(即,不保证存放元素的顺序和取出顺序一致)
5.不能有重复元素/对象。
2.1 案例1
2.2 案例2
2.3 案例3
2.4 链表模拟
HashSet底层是HashMap,HashMap底层是(数组+链表+红黑树)
三、HashSet源码解析
3.1 源码解析
1.HashSet底层是HashMap,第一次添加时,table数组扩容到16,临界值(threshold)是16*加载因子,(loadFactor)是0.75=12;
如果table数组使用到了临界值12,就会扩容到16*2=32,新的临界值就是32*0.75=24,依次类推。
2.添加一个元素时,先得到hash值-会转成->索引值;
3.找到存储数据表table,看这个索引位置是否已经存放的有元素;
4.如果没有,直接加入;
5.如果有,调用equals比较,如果相同,就放弃添加,如果不相同,则添加到最后;
6.在java8中,如果一条链表的元素个数到达treeify_threshold(默认是8),并且table的大小>=min_treeify_capacity(默认64),就会进行树化(红黑树)。
详细参见HashMap源码
3.2 debug设置
、
3.3 扩容机制debug测试
3.4 树化debug测试
3.5 equals解释
3.6 size Debug解释
size就是我们每加入一个结点Node(k, v, h, next),不管是加在table表的某一个位置,还是加在table表的某一条链表上
3.7 练习
定义一个Employee类,该类包含:private成员属性name,age要求:
创建3个Employee对象放入HashSet中,当name和age的值相同时,认为是相同员工,不能添加到HashSet集合中