淺談hashmap

? ? ? ? 學(xué)習(xí)了java這么久沒有看過hashmap源碼舔涎,近期才來了解hashmap的底層結(jié)構(gòu),雖然網(wǎng)上有很多關(guān)于hashmap的文章但是我還是想學(xué)習(xí)總結(jié)一下蠢琳。

? ? ? ? 在jdk1.8之前hashmap是數(shù)組+鏈表的形式狂男,jdk1.8變成了數(shù)組+鏈表+紅黑樹的結(jié)構(gòu)恢恼,核心都是為了提高查詢速度,現(xiàn)在聊下hashmap的數(shù)據(jù)結(jié)構(gòu)基于jdk1.8幻件。

基礎(chǔ)結(jié)構(gòu)圖
node類

node對(duì)象屬性

hash:key的哈希值

key:節(jié)點(diǎn)的key卸例,類型和定義HashMap時(shí)的key相同

value:節(jié)點(diǎn)的value,類型和定義HashMap時(shí)的value相同

next:該節(jié)點(diǎn)的下一節(jié)點(diǎn)

????????當(dāng)它第一次put時(shí)候始苇,它才會(huì)進(jìn)行初始化擴(kuò)容默認(rèn)大小capacity是16第二次是32第三次是64就算設(shè)置初始化20砌烁,大小也是32,每次擴(kuò)容都是2的冪催式,之所以每次擴(kuò)容都為2的冪是為了符合Hash算法均勻分布的原則函喉,防止取模運(yùn)算后有些index結(jié)果的出現(xiàn)幾率會(huì)更大,而有些index結(jié)果永遠(yuǎn)不會(huì)出現(xiàn)荣月,為了index分布的更加均勻管呵,所以采取2的冪〔刚可以參考hashmap

????????每次進(jìn)行put時(shí)捐下,他會(huì)計(jì)算key的hash值账锹,然后通過位運(yùn)算進(jìn)行取模(n -1) & hash,然后求出放置到數(shù)組的i位置坷襟,如果tab[i]為空奸柬,將node放置到這個(gè)位置,同時(shí)node.next為null啤握,如果tab[i]不為空將會(huì)進(jìn)行判斷這個(gè)key值是否相等(畢竟hashcode肯定是相同)鸟缕,如果key值相等將會(huì)替換掉這個(gè)node,如果key值不相等將會(huì)在這個(gè)node插入在鏈表的最前端排抬,next連著之前的node懂从,就類似(HashMap會(huì)這樣做:B.next = A,table[0] = B,如果又進(jìn)來C,index也等于0,那么C.next = B,table[0] = C)。

? ? ? ?而且hashmap還有個(gè)負(fù)載因子loadFactor(默認(rèn)0.75)蹲蒲、capacity容量大蟹Α(默認(rèn)16)和threshold(loadFactor * capacity),這個(gè)負(fù)載因子主要是用來衡量HashMap滿的程度届搁,它主要是設(shè)置一個(gè)界限缘薛,當(dāng)map的容量除以capacity總?cè)萘看笮?gt;=loadFactor,其實(shí)就是map當(dāng)前容量大于threshold將會(huì)進(jìn)行擴(kuò)容卡睦。

put方法

? ? ? ? 如果當(dāng)鏈表的節(jié)點(diǎn)的長度大于TREEIFY_THRESHOLD(默認(rèn)是8宴胧,雖然判斷是bincont>=7但是由于for循環(huán)是給p.next進(jìn)行賦值,所以當(dāng)bincont為7的時(shí)候他的鏈表長度已經(jīng)是8了)的時(shí)候?qū)?huì)轉(zhuǎn)成紅黑樹表锻,但是如果tab長度小于MIN_TREEIFY_CAPACITY(默認(rèn)值是64)恕齐,它不會(huì)轉(zhuǎn)紅黑樹而是將進(jìn)行擴(kuò)容再次散列((n -1) & hash取模,因?yàn)閿U(kuò)容后長度變動(dòng)瞬逊,重新散列后node下標(biāo)會(huì)變動(dòng)達(dá)到防止鏈表過長的目的)避免鏈表過長显歧。


鏈表轉(zhuǎn)紅黑樹《

????????因?yàn)閔ashmap是非線程安全的,如果多線程操作hashmap擴(kuò)容時(shí)可能會(huì)發(fā)生死鎖的問題确镊,假設(shè)我們有兩個(gè)線程A士骤、B,hashmap容量為2蕾域,A線程放入key T1拷肌、T2、T3旨巷、T4廓块、T5,同時(shí)T1契沫、T2和T3的hash值相同带猴,形成一個(gè)鏈表T1->T2->T3,而T4、T5hash值不相同懈万,于是這時(shí)候容量不足拴清,需要進(jìn)行擴(kuò)容(rehash)靶病,于是新建一個(gè)更大容量的hash表,將數(shù)據(jù)從老的hash表中進(jìn)行遷移口予,這時(shí)候B線程進(jìn)來了娄周,A線程掛起,這時(shí)候B線程發(fā)現(xiàn)容量不足也需要擴(kuò)容沪停,這時(shí)候線程B擴(kuò)容的之后的鏈表為T1->T2,然后B線程執(zhí)行完了煤辨,A線程繼續(xù)執(zhí)行,將鏈表變成了T2->T1,這時(shí)候形成了T1.next=T2木张,T2.next=T1,所以當(dāng)用戶對(duì)這個(gè)key進(jìn)行取值的時(shí)候?qū)?huì)陷入死循環(huán)卡在那沒有反應(yīng)众辨。

? ? ? ? 如果需要多線程操作hashmap可以使用ConcurrenHashmap進(jìn)行替代,ConcurrenHashmap是一個(gè)線程安全的hashtable舷礼,這時(shí)候就有人問為什么不直接使用hashtable鹃彻,雖然hashtable也是線程安全的但是hashtable鎖定的是一整個(gè)hash表,效率較為低下妻献,而ConcurrenHashmap可以做到讀取數(shù)據(jù)不進(jìn)行加鎖實(shí)現(xiàn)段鎖蛛株,因?yàn)槠鋬?nèi)部結(jié)構(gòu)有個(gè)Segment的存在,使其進(jìn)行寫操作的時(shí)候可以將鎖的粒度保持盡量小育拨。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末谨履,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子熬丧,更是在濱河造成了極大的恐慌笋粟,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件锹引,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡唆香,警方通過查閱死者的電腦和手機(jī)嫌变,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來躬它,“玉大人腾啥,你說我怎么就攤上這事》胂牛” “怎么了倘待?”我有些...
    開封第一講書人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長组贺。 經(jīng)常有香客問我凸舵,道長,這世上最難降的妖魔是什么失尖? 我笑而不...
    開封第一講書人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任啊奄,我火速辦了婚禮渐苏,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘菇夸。我一直安慰自己琼富,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開白布鞠眉。 她就那樣靜靜地躺著械蹋,像睡著了一般。 火紅的嫁衣襯著肌膚如雪朝蜘。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評(píng)論 1 297
  • 那天谱醇,我揣著相機(jī)與錄音副渴,去河邊找鬼全度。 笑死,一個(gè)胖子當(dāng)著我的面吹牛将鸵,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播顶掉,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼痒筒,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了簿透?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤葡盗,失蹤者是張志新(化名)和其女友劉穎戳粒,沒想到半個(gè)月后路狮,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蔚约,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡苹祟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年树枫,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片砂轻。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖厨喂,靈堂內(nèi)的尸體忽然破棺而出庄呈,到底是詐尸還是另有隱情,我是刑警寧澤斜纪,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布文兑,位于F島的核電站,受9級(jí)特大地震影響绿贞,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜贮聂,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一寨辩、第九天 我趴在偏房一處隱蔽的房頂上張望歼冰。 院中可真熱鬧,春花似錦隔嫡、人聲如沸甘穿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至届垫,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間全释,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來泰國打工妄迁, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留判族,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓形帮,卻偏偏與公主長得像周叮,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子合冀,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353