/**
* 根據(jù)容量參數(shù),返回一個2的n次冪的table長度。
*/
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;
}
先看一下tableSizeFor()的輸入與輸出
public static void main(String[] args) {
System.out.println(tableSizeFor(1));
System.out.println(tableSizeFor(5));
System.out.println(tableSizeFor(25));
System.out.println(tableSizeFor(125));
System.out.println(tableSizeFor(625));
}
輸出:
1
8
32
128
1024
通過輸出可以大致猜到tableSizeFor的作用是返回一個大于輸入?yún)?shù)且最小的為2的n次冪的數(shù)。
我們再來看看是怎么做到的。
當輸入為25的時候,n等于24,轉(zhuǎn)成二進制為1100,右移1位為0110,將1100與0110進行或("|")操作,得到1110。接下來右移兩位得11,再進行或操作得1111,接下來操作n的值就不會變化了。最后返回的時候,返回n+1,也就是10000,十進制為32。按照這種邏輯得到2的n次冪的數(shù)。
再來看一個例子,當n=1<<30的時候:
01 00000 00000 00000 00000 00000 00000 (n)
01 10000 00000 00000 00000 00000 00000 (n |= n >>> 1)
01 11100 00000 00000 00000 00000 00000 (n |= n >>> 2)
01 11111 11000 00000 00000 00000 00000 (n |= n >>> 4)
01 11111 11111 11111 00000 00000 00000 (n |= n >>> 8)
01 11111 11111 11111 11111 11111 11111 (n |= n >>> 16)
由于int類型為32位,所有即使除符號為之外只有第一位為1的情況,也能將所有的位全部變成1,不過由于最后計算出來為int類型的最大值,此時返回n+1會導致溢出,不能返回期望的結(jié)果,這也是為什么在方法開始是要執(zhí)行int n = c - 1;的原因。
那么又有一個問題,為什么要在前面減1,然后在后面加回來呢?當輸入為0的時候就會發(fā)現(xiàn),方法的輸出為1,HashMap的容量只有大于0時才有意義。