ConcurrentHashMap#tableSizeFor分析

ConcurrentHashMap中在建立時,會調用tableSizeFor方法進行計算嘗試容量大小,這個方法原理就是經過巧妙的位運算,獲取最接近入參的2的冪次方數。
簡單思考,若是這個數自己不是2的冪次方,如何根據這樣的數,計算最接近2的冪次方數呢?首先任意一個數,均可以表示爲00...01XXX...XXX, 那麼最接近它的2冪次方數確定是最高位左移一位,低位全0,即:00...10000...000,那麼如何獲得這樣的數呢?仔細觀察發現,00...10000...000,其實就是00...01111...111+1得,因此問題就轉爲了如何求從最高位開始,低位全1的數,而這種數,咱們能夠經過位運算+或運算獲得。java

private static final int tableSizeFor(int c) {
        // 減一是針對入參c剛好是二的冪次方數
        // 此時經移位後輸出應該仍是c自己
        int n = c - 1;
        //經過移位加或運算,使n最終變成00...01111...111
        // 移16位爲止,是由於int型數據,總共32位,移動16恰好
        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;
    }

舉例:一個奇數
原始入參: 00...01XXX...XXX1
參數減一: 00...01XXX...XXX0
左移一位:00...001XX...XXX0
求或: 00...011XX...XXX0
左移二位: 00...00011X...XXX0
求或: 00...01111x...XXX0
...
發現規律沒?每次移n位(n爲2的冪次方),再與移位前的數求或,會使從高位開始的n位變成1,最終
移16位,正好變成: 00...011111...1111,此時原來的數,就變成了從高位開始全1的數,這個時候,獲取最接近它的冪次方數就很是簡單了,直接加1,
變成:00...011111...1111-->00...100000...0000code

相關文章
相關標籤/搜索