putVal()源码注释
/**
* HashMap putVal方法(put()调用)
* @param hash
* @param key
* @param value
* @param onlyIfAbsent
* @param evict
* @return
*/
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
HashMap.Node<K,V>[] tab; HashMap.Node<K,V> p; int n, i;
/*检查是否初始化table数组*/
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
/*如果hash对应的下标位置中没有元素(n-1)&hash与hash%n等价,
(n-1)&hash使用的位运算,效率比模运算高*/
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
else {//下标位置已经有元素了
HashMap.Node<K,V> e; K k;
/*这个元素可能是就是本身,把p赋给e(p就是新插入进来的节点)*/
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
/*如果这个位置是红黑树存储了多个Node,就把p转换为TreeNode,然后插入红黑树*/
else if (p instanceof HashMap.TreeNode)
e = ((HashMap.TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
/*拉链法解决hash冲突*/
else {
for (int binCount = 0; ; ++binCount) {
/*p指向的就是链表的第一个元素,e指向p的下一个,
为空意味着要把新插入的节点新增到拉链链表后面*/
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null);
/*TREEIFY_THRESHOLD默认值是8*/
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);//链表转红黑树
break;
}
/*遍历到了自己*/
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
/*把p往下移*/
p = e;
}
}
/*e指向的是新node(可能是旧key+新值,也可能是新key+新值)*/
if (e != null) { // existing mapping for key
V oldValue = e.value;
/*onlyIfAbsent为ture表示不更改旧值*/
if (!onlyIfAbsent || oldValue == null)
e.value = value;
/*在LinkedHashMap中实现,在这里算是空方法*/
afterNodeAccess(e);
return oldValue;
}
}
/**
* modCount表示HashMap发生更改的次数,
* 作用是fail-fast,会判断expectModCount和modCount是否相等,
* 如果不相等意味着其他线程修改了HashMap,会报ConcurrentModificationException
*/
++modCount;
/*size表示的是真实元素个数*/
if (++size > threshold)
resize();
/*在这里是空方法,在LinkedHashMap中实现*/
afterNodeInsertion(evict);
/*插入的是新key+新value的时候会返回null*/
return null;
}
resize()源码注释
final HashMap.Node<K,V>[] resize() {
HashMap.Node<K,V>[] oldTab = table;
int oldCap = (oldTab == null) ? 0 : oldTab.length;
int oldThr = threshold;
int newCap, newThr = 0;
/*第一次put不会进入这个判断,因为在构造方法中,table并没有初始化*/
if (oldCap > 0) {
if (oldCap >= MAXIMUM_CAPACITY) {
threshold = Integer.MAX_VALUE;
return oldTab;
}
else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
oldCap >= DEFAULT_INITIAL_CAPACITY)
newThr = oldThr << 1; // *2
}
/*new HashMap(10)的情况,
* 在构造方法中会threshhold = tableSizeFor(10) = 16*/
else if (oldThr > 0)
newCap = oldThr;
/*new HashMap()的情况*/
else {
newCap = DEFAULT_INITIAL_CAPACITY;
newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
}
/*new HashMap(10)&&第一次resize()才会进入
* 目的是初始化map的threshold*/
if (newThr == 0) {
float ft = (float)newCap * loadFactor;
newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?
(int)ft : Integer.MAX_VALUE);
}
threshold = newThr;
@SuppressWarnings({"rawtypes","unchecked"})
HashMap.Node<K,V>[] newTab = (HashMap.Node<K,V>[])new HashMap.Node[newCap];
table = newTab;
/*第一次put不会进入这个判断
* 目的是把旧table中的内容映射到新table
* 只有两种情况,要么在原来的下标上,要么在2*原来下标上*/
if (oldTab != null) {
for (int j = 0; j < oldCap; ++j) {
HashMap.Node<K,V> e;
if ((e = oldTab[j]) != null) {
oldTab[j] = null;
if (e.next == null)
newTab[e.hash & (newCap - 1)] = e;
else if (e instanceof HashMap.TreeNode)
((HashMap.TreeNode<K,V>)e).split(this, newTab, j, oldCap);
else { // preserve order
HashMap.Node<K,V> loHead = null, loTail = null;
HashMap.Node<K,V> hiHead = null, hiTail = null;
HashMap.Node<K,V> next;
do {
next = e.next;
if ((e.hash & oldCap) == 0) {
if (loTail == null)
loHead = e;
else
loTail.next = e;
loTail = e;
}
else {
if (hiTail == null)
hiHead = e;
else
hiTail.next = e;
hiTail = e;
}
} while ((e = next) != null);
if (loTail != null) {
loTail.next = null;
newTab[j] = loHead;
}
if (hiTail != null) {
hiTail.next = null;
newTab[j + oldCap] = hiHead;
}
}
}
}
}
return newTab;
}