讀HashMap源碼之tableSizeFor

 /**
     * Returns a power of two size for the given target capacity.
     */
    static final int tableSizeFor(int cap) {
        int n = cap - 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;
    }

源碼的解釋是:返回一個指定容量大小的2次冪,人話就是說返回比給定參數大的、最接近的2的n次方那個數


即如果傳入10,返回2^4 = 16、傳入18,返回2^5 = 32,傳入34,應該返回2^6 = 64
測試一下

 public static void main(String[] args) {
        System.out.println("傳入10----"+tableSizeFor(10));
        System.out.println("傳入18----"+tableSizeFor(18));
        System.out.println("傳入34----"+tableSizeFor(34));
    }

    static final int tableSizeFor(int cap) {
        Integer MAXIMUM_CAPACITY = 1 << 30;
        int n = cap - 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;
    }

結果:
在這裏插入圖片描述
怎麼來的呢?先認識一下兩個運算符|>>>
|不用多說,二進制或,兩個都爲0才爲0
>>>,無符號右移

無符號右移,忽略符號位,空位都以0補齊

10進制轉二進制的時候,因爲二進制數一般分8位、 16位、32位以及64位(java是四個字節32位) 表示一個十進制數,所以在轉換過程中,最高位會補零
來動手算一個,傳入10

 int n = cap - 1;

後n = 9

 n |= n >>> 1;

先算n >>> 1,再算n= n|前面的結果
在這裏插入圖片描述

同理,在計算```n |= n >>> 2;``,此時n已經等於13了
在這裏插入圖片描述

同理,在計算```n |= n >>> 4;``,此時n已經等於15了

在這裏插入圖片描述
到此可以看出,它的每一次運算,都是在將有0的位轉換成1,直到所有位都爲1爲止

最後返回的時候return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;如果比最大值小,就返回運算結果+1,又正好將所有的1轉換成了0,且進了一位,剛好是2^x次方

採用這樣的算法,精妙之處就在於二進制運算更快

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