以下都是本人在自学中对知识的理解,可能有许多不足之处,还望多多包含,若能帮助到你,倍感荣幸
HashSet的底层是HashMap
//HashSet无参构造
public HashSet() {
map = new HashMap<>();
}
public HashMap() {
this.loadFactor = DEFAULT_LOAD_FACTOR; // 默认负载因子0.75
}
4个构造器
add方法
// HashSet add()方法
public boolean add(E e) {
// HashMap 是传入 key-value ,而 HashSet把 仅传入key ,values默认是一个常量
return map.put(e, PRESENT)==null;
}
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
// hash()方法,通过hashCode值 经过运算 得到 hash , 注意:hashCode值 不等于 hash
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i; // 局部变量(辅助作用)
// 判断table表数组是不是为null ,或 长度为 0 ,是的话 则进行扩容 ,默认情况下 扩容为 16
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
// 通过 hash值 再次经过运算 得到 对应的 table表的索引 ,判断该索引处是否为 null ,若为null
// 则在索引位置直接添加该元素
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
else {
Node<K,V> e; K k;
// 如果该索引有元素的话 ,则先判断 该元素 与 key 是否相同
// key相同的判断标准: == 相同 或 调用 所添加元素的equals()方法判断 ,二者有一则相同
if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k))))
e = p;
// 如果第一个元素不相同,则在判断 该索引所在的结构是不是一棵红黑树 ,
// 是树的话,则在树里进行添加操作
else if (p instanceof TreeNode)
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
//如果 第一个元素不同 ,所在结构又不是一棵树 ,那就for循环遍历该链表所有元素
//判断是否有相同元素 ,有相同就放弃添加,替换value ,没有就添加到链表末尾
else {
for (int binCount = 0; ; ++binCount) { // 死循环
if ((e = p.next) == null) { // 判断下一个元素是不是null ,是null则添加
p.next = newNode(hash, key, value, null);
// 添加完成后 判断是否进行树化
if (binCount >= TREEIFY_THRESHOLD - 1)
treeifyBin(tab, hash);
break;
}
// 如果下一个元素不是null ,则比较 hash 和 key 是否相同
// 相同则跳出for , 不同则继续for 比较下一个元素
if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
}
// 如果元素相同(重复),则 新key的 value 取代 旧key的value
if (e != null) {
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
}
++modCount;
// 已添加元素个数超过阈值则扩容 threshold = table表数组长度 * 负载因子
if (++size > threshold)
resize();
afterNodeInsertion(evict);
return null;
}
以上都是本人在自学中对知识的理解,可能有许多不足之处,请多多包含