HashSet的底层是HashMap,HashMap的底层是使用 transient Node<K,V>[] table; 这样一个数组来保存对象
每个节点Node类的信息如下:
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key; // 为放进 HashSet集合的值
V value; // 一个不变的 Object对象 final new Object()
Node<K,V> next;
}
确定Node节点在table数组中的下标计算方式: index=node.hash & (newCap - 1) ,newCap为扩容后的容量大小,所以每次扩容时会遍历旧数组,获取Node节点,根据node对象的hash值重新计算该节点位于新数组的位置
底层HashMap中从链表到树化成红黑树的过程
树化的条件:
1、数组的容量>=64
2、单个链表的节点个数超过8个,注意这个节点个数不包括位于数组中的节点(比如下图的 key=1),但包括新加入的节点
debugger代码:
public class HashSetSource {
public static void main(String[] args) {
HashSet hashSet = new HashSet<>();
for(int i=1;i<=11;i++){
/**
* debugger的时候,需要注意
* i=9,数组容量由 16 ——》32
* i=10,数组容量由 32 ——》64
* i=11,链表树化成红黑树
*/
hashSet.add(new A(i));
}
hashSet.add(12);
hashSet.add(12);
}
}
class A{
private int n;
public A(int n) {
this.n = n;
}
@Override
public int hashCode() {
return 100;
}
}