ConcurrentHashMap --- 數組大小的確定


為了實現一個通過 Hash 尋址的方式,獲得存儲的元素,首先要考慮的選擇何種 Hash 算法。 HashMap 選擇了近似於取模的方式,獲得元素存儲的位置。當然為了提高性能,且降低key 的碰撞。HashMap主要做了兩方面的優化

 

1. 對Hash取值的優化

我們當然可以直接選擇存儲的 key 的 hashcode() 方法得到 key 的 hash 值。但是對一些hashcode值比較接近的key,可能會造成存儲時,分配不均。通常情況下,決定key 分配位置的其實是 key 的hash 值的低位部分。所以,為了

讓 hash 值在分配時更加均勻,可以采用如下方法

static final int spread(int h) {
        return (h ^ (h >>> 16)) & 0x7fffffff;
}

 

2. 對數組大小的優化

一般情況下,我們可以直接采用 hash % CAP (CAP為具體存儲數組的大小) 得到某個 key 在數組的下標。但這種取模的方式相對性能較低,HashMap 采用了另外一種方式,即將數組的容量設定為 2 的 n 次冪,再使用 與 的形式獲得下標。

這里面主要涉及到了如下算法

/**
     * Returns a power of two table size for the given desired capacity.
     * See Hackers Delight, sec 3.2
     */
    private static final int tableSizeFor(int c) {
        int n = c - 1;
        n |= n >>> 1;
        n |= n >>> 2;
        n |= n >>> 4;
        n |= n >>> 8;
        n |= n >>> 16;
        return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
    }

進行下標的計算時,我們可以使用如下方式得到:

(spread(key.hashcode() & (table.length-1))  

上述 tableSizeFor 方法的目的是找到比給定 c 最近的 2 的 n 次冪的最小值

 

至於 tableSizeFor  方法的原理,大家可以參考一下這篇文章

 

 

參考資料:

1  HashMap 源碼解析

HashMap tableSizeFor

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM