HashMap擴(kuò)容大小為什么是2的冪

1、前言

??在回答這個問題之前,我們可以回顧一下HashMap的存取過程,當(dāng)執(zhí)行putVal的操作的時候,

  • 首先檢查大小,看是否需要擴(kuò)容(默認(rèn)元素超過最大值的0.75時擴(kuò)容),如果需要擴(kuò)容就進(jìn)行擴(kuò)容

  • 然后計算出key的hashcode,根據(jù)hashcode定位數(shù)值所在的bucketIndex

  • 如果該位置上沒有元素,就直接插入,結(jié)束

  • 如果該位置上有元素就使用equal比較是否相同

  • 如果key相同就把新的value替換舊的value,結(jié)束

  • 如果key不同,就繼續(xù)遍歷,找到根節(jié)點(diǎn),如果沒找到key的話,就構(gòu)造一個新的節(jié)點(diǎn),然后把節(jié)點(diǎn)插入到鏈表尾部,表示put成功(jdk 1.8 之后鏈表長度超過閾值就會轉(zhuǎn)化為紅黑樹)

2、詳解

??好了,一個put操作就這樣完成了,按照我們理想的狀況,hashMap的存取就是O(1),也就是直接根據(jù)hashcode就可以找到它,每個bucket只存儲一個節(jié)點(diǎn),鏈表指向都是null,這樣就比較開心了,不要出現(xiàn)一個鏈表很長的情況。

??所以我們希望它能分布的均勻一點(diǎn),如果讓我們設(shè)計的話,我們肯定是直接對長度取模-----hashcode % length,但HashMap的設(shè)計者卻不是這樣寫的,它寫成了2進(jìn)制運(yùn)算,如下:

static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

index = (n - 1) & hash

??為什么設(shè)計成(n - 1) & hash 這樣呢?在 n 為 2次冪的情況下時,(n - 1) & hash ≈ hash % n ,因?yàn)?進(jìn)制的運(yùn)算速度遠(yuǎn)遠(yuǎn)高于取模,所以就使用了這種方式,所以要求為2的冪。

??我們可以看到它求hash的過程,將32位的hashCode值向右移動16位,高位補(bǔ)0,也就是只要了高16位,這是為什么呢?因?yàn)閔ashcode的計算方法導(dǎo)致哈希值的差異主要在高位,而 (n - 1) & hash是忽略了容量以上的高位的,所以 使用h >>>16就是為了避免類似情況的哈希沖突

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • HashMap 是 Java 面試必考的知識點(diǎn),面試官從這個小知識點(diǎn)就可以了解我們對 Java 基礎(chǔ)的掌握程度。網(wǎng)...
    野狗子嗷嗷嗷閱讀 6,810評論 9 107
  • 1.概述 HashMap是日常java開發(fā)中常用的類之一,是java設(shè)計中非常經(jīng)典的一個類,它巧妙的設(shè)計思想與實(shí)現(xiàn)...
    Garwer閱讀 2,375評論 1 28
  • 作為標(biāo)準(zhǔn)一個大三黨,在你們高考結(jié)束后咨詢了眾多學(xué)長學(xué)姐,迫不及待有很多想法想要和你們分享,我?guī)缀鯇懥似ё值恼撐?..
    Jenny愛青梅閱讀 180評論 1 0
  • 小時候,冒險是打娘胎里帶出來的一種野性。在這種野性驅(qū)使之下,12歲之前,我們一群同齡的孩子暗地里進(jìn)行過許多秘密活動...
    癢癢不撓閱讀 451評論 0 1
  • 晶瑩剔透的雪花, 如同曼妙玲瓏的少女, 悠然落下, 投入大地的懷抱。 大地伸出雙臂, 滿心歡喜地與雪花相擁相依, ...
    雨花石_fc62閱讀 383評論 0 2

友情鏈接更多精彩內(nèi)容