看HashMap的源碼時(shí),發(fā)現(xiàn)了里面好多很不錯(cuò)的算法。
tableSizeFor的功能(不考慮大于最大容量的情況)是返回大于輸入?yún)?shù)且最近的2的整數(shù)次冪的數(shù)。比如10,則返回16。
該算法源碼如下:
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;
}
詳解如下:
先來(lái)分析有關(guān)n位操作部分:先來(lái)假設(shè)n的二進(jìn)制為01xxx...xxx。接著
對(duì)n右移1位:001xx...xxx,再位或:011xx...xxx
對(duì)n右移2為:00011...xxx,再位或:01111...xxx
此時(shí)前面已經(jīng)有四個(gè)1了,再右移4位且位或可得8個(gè)1
同理,有8個(gè)1,右移8位肯定會(huì)讓后八位也為1。
綜上可得,該算法讓最高位的1后面的位全變?yōu)?。
最后再讓結(jié)果n+1,即得到了2的整數(shù)次冪的值了。
由于int是32位,所以>>>16便能滿足。
現(xiàn)在回來(lái)看看第一條語(yǔ)句:
int n = cap - 1;
讓cap-1再賦值給n的目的是另找到的目標(biāo)值大于或等于原值。例如二進(jìn)制1000,十進(jìn)制數(shù)值為8。如果不對(duì)它減1而直接操作,將得到答案10000,即16。顯然不是結(jié)果。減1后二進(jìn)制為111,再進(jìn)行操作則會(huì)得到原來(lái)的數(shù)值1000,即8。
HashMap里的MAXIMUM_CAPACITY是230。我結(jié)合tableSizeFor()的實(shí)現(xiàn),猜測(cè)設(shè)置原因如下:
int的正數(shù)最大可達(dá)231-1,而沒(méi)辦法取到231。所以容量也無(wú)法達(dá)到231。又需要讓容量滿足2的冪次。所以設(shè)置為230。