1.8 hashMap.resize()的 重新散列算法

源碼
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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章