源碼
resize()的代碼片段
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;
}
算法原理: e.hash & oldCap == 0 放在原數組,其餘的座標+oldCap。這時只有hash在oldCap最高位的二進制爲1纔不能與0。這個改進算法和hash&(length-1)散列結果是一致的。
比如oldCap:16(10000),最高位就是第5位,即xxxxx1xxxx這樣的hash值。這是因爲10000與上任何數只能等於0或者16。
假設 oldCap(舊容量):16 newCap(新容量):32。
當hash<16時,不管擴容多少次散列值都一定在oldCap內,因爲大於的16的高位一定是0。
比如 hash = 15
原大小:
01111(15) & 10000(16) =01111
擴容後:
01111(15) & 100000(32) =01111
hash&(length-1):
01111(15) & 011111(31) =01111
當hash>16時,新的散列值爲原值+擴容大小,因爲每擴容一次即左移1位(oldCap<<1),相當於加上2的n次方(比如oldCap=16,n就是4)
比如 hash = 31
原大小:
011111(31) & 10000(16) =01111
擴容大小:
011111(31) & 100000(32) =011111
hash&(length-1):
011111(31) & 011111(31) =011111
在進行散列運算的時候大於最高位的都是按0處理,在進行hash&(oldCap-1)運算時最高只能是oldCap-1。比如hash=31,odlCap=16 hash&(oldCap-1)=15