特点
- 实现了set接口,底层是HashMap,HashMap线程不安全,其无参构造方法如下
public HashSet() { map = new HashMap<>(); }
- 可以存放null值,但是只能有一个
- 不保证元素是有序的,取决于hash后,确定的索引结果,不保证存放顺序和取出顺序一致
- 不能有重复元素
- 底层是数组+链表+红黑树
- 调用无参构造,初始容量为16
插入细节
- 添加一个元素,先得到hash值,再转成索引值
- 找到存储数据表table,看这个索引位置是否已经存放的有元素,如果没有,直接加入,如果有就调用equals比较,如果相同就放弃添加,否则添加到最后,【HashMap 比较key是否相同,相同就直接替换】
- 一条链表的元素个数达到默认值(8),并且table的大小大于默认值(64),此链表就会进行树化(红黑树),table的大小就行hashSet中所有元素的个数
- 【HashMap 底层维护了Node类型的数组table,默认为null】
- 当创建对象时,将加载因子初始化为0.75
- 第一次添加,需要扩容table容量为16,临界值为12,以后再次扩容,则需要扩容table容量为原来的2倍
面试题
set.add(new String("上好"));
set.add(new String("上好"));
第二个加不进去的,String的equals比较的是字面量
LinkedHashSet![](https://i-blog.csdnimg.cn/blog_migrate/483a2138aa22e9134d5fcb5c0e9f1e42.png)
- 是HashSet的子类,扩容机制一样,因子也是0.75
- 底层维护的是LinkedHashMap 即是数组table+双向链表+红黑树,维护有个head头节点和tail尾节点
- 加入顺序和取出顺序是一致 子类扩展的操作针对于HashSet
- 第一次添加时候,直接将table数组扩容到16
- 数组类型是HashMap$Node[] ,存放的节点类型是LinkedHashMap$Entry,每个节点有个before和after属性,指向前节点和后节点