HashSet源码
add()方法第一次添加元素分析
package com.JiHe_.Set_;
import java.util.HashSet;
public class Demo {
public static void main(String[] args) {
HashSet<Object> hashSet = new HashSet<>();
hashSet.add("java");
hashSet.add("lyc");
hashSet.add("java");
System.out.println("hashSet"+hashSet);
/*
源码解读
1.执行HashSet
public HashSet() {
map = new HashMap<>();
}
2.执行一个add方法
public boolean add(E e) {//这里的e是字符串常量(java)
return map.put(e, PRESENT)==null; // static PRESENT = new Object();
//若为true则添加成功
}
3.put方法,该方法会执行hash(key)方法
public V put(K key, V value) {//key=“java”,value=PRESENT,无实际意义,起到占位的作用
return putVal(hash(key), key, value, false, true);
}
4.hash(key)会得到key对应的hash值
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);//无符号右移16位,是降低hash冲突几率
}
5.执行putVal(hash(key),
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,就是HashMap的一个数组,类型是Node[]数组
//if语句表示,如果table为空,或者数组长度为0,就第一次扩容table的空间到16
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;//执行完本语句,table已获得16的大小
//(1)根据传入key的hash值,去计算key应该存放在table标的哪个索引位置,
//并把这个位置的对象赋给p
//(2)继续判断p是否为空
(2.1),如果p为空表示,还没有存放元素,就创建一个Node,key是真正存放的对象,value就是占位的PRESENT,hash的作用是用来判断下一个进来的值,如果下一个元素的
hash值不相等,就会在该元素的后面添加。
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);//直接放在该位置
else {
Node<K,V> e; K k;
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
else if (p instanceof TreeNode)