/**
* 根據(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時才有意義。