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