final Node<K,V>[] resize() {
// ...省略不重要的
}
|
for (int j = 0; j < oldCap; ++j) {
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 TreeNode)
((TreeNode<K,V>)e).split(this, newTab, j, oldCap);
else { // preserve order
Node<K,V> loHead = null, loTail = null;
Node<K,V> hiHead = null, hiTail = null;
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;
}
}
}
}
final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) {
// ...省略不重要的
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
else {
// ...省略不重要的
}
|
长度n=8 ----> 0x1000
n-1 ----> 0x0111
此时写入两个元素,两个元素的hash值分别为hash1 = 0x0101,hash2 = 0x1101
hash1 & n-1 = 0x0101
hash2 & n-1 = 0x0101
两个hash取模后的结果是一致的,所以它们会在同一个地方组成链表
那么此时如果要进行扩容移位呢?
hash1 & n = 0x0000
hash2 & n = 0x1000
此时两者的结果是不一样的,并且相差0x1000即10进制的8即数组长度.。
所以这也就是为什么上图15行只判断==0的原因,因为这个取模结果只有0和1两种值(数组长度是2的n次方,只有除了符号位外的最高位为1)
而两个取模结果等于数组长度,这也就是为什么上图第32和36行那么处理的原因。