Java8—HashMap之tableSizeFor()

看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便能滿足。

舉個(gè)栗子.jpg

現(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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容