1. 程式人生 > >HashMap和ConcurrentHashMap 源碼關鍵點解析

HashMap和ConcurrentHashMap 源碼關鍵點解析

pack https -a 加鎖 this 系列文章 如果 zha 是不是

第一部分:關鍵源碼講解

1.HashMap 是如何存儲的?

a.底層是一個數組 tab

b. hash=hash(key) ,然後根據數組長度n和hash值,決定當前需要put的元素對應的數組下標,

hash算法見紅框。

技術分享圖片

2.數組長度是固定的,HashMap 可以無限put(k,v) ,為什麽?

HashMap 的元素個數大於threshold的時候,會進行resize() 擴容

技術分享圖片

3.如何實現擴容的?

擴容就是通過 resize() , 重新創建一個新數組,對所有元素rehash,放到新數組相應位置。

擴容代價是很大的,所以很多公司編碼規範都有一條,合理設置hashMap的InitialCapicity,

禁止直接用HashMap()

技術分享圖片

4.Hash 沖突是什麽?怎麽解決這個問題?

Hash 沖突: 假如一個學校有366個同學,一年365天,那麽至少有兩個同學是同一天生日,這就是hash沖突。用代碼來說,不同的key 經過計算p = tab[i = (n - 1) & hash] 對應同一個p

如何解決:

p在有的翻譯文檔中叫桶,一個桶可以裝多個,怎麽裝? 鏈表或者紅黑樹。

技術分享圖片

以上代碼中 else if 部分是紅黑樹

else 部分是鏈表 ,鏈表中如果沖突元素個>=TREEIFY_THRESHOLD-1,會將鏈表轉換成紅黑樹。

因為元素個數很多時,紅黑樹比鏈表性能更好。

5.HashMap 是不是線程安全的,如何解決線程安全問題?

技術分享圖片

答案是NO,如何解決:

a.對整個map加鎖。

b.直接用ConcurrentHashMap

技術分享圖片

對f加鎖了,就是對桶加鎖,就是傳說中的分段鎖機制。

在保證安全的前提下,加鎖的範圍越小,則程序性能越高,自己寫代碼時切記胡亂在方法上加synchronized

6.HashMap 和 hash() equals() 方法的關系

面試中面試官會問重寫equals()方法要註意是什麽,答案是hash()也要重寫。

不重寫會引起HashMap 等集合類使用的混亂。

技術分享圖片

比如類Person(id,name),重寫了 equals(Object obj){... reutrn this.id==obj.id},沒有重寫hash(), 那麽從類定義上來說,只要id相等就是同一個人,當我們Person作為key,放入兩個Person對象(id相等)到HashMap的時候,那麽就翻車了,HashMap 會有兩個元素,而我們期望的只保留一個。

第二部分:實驗驗證

1.驗證ConcurrentHashMap 線程安全。

技術分享圖片 技術分享圖片

2.重寫equals()不重寫hash() 翻車問題驗證。

需要源碼或者需要系列文章更新通知,請加微信 kevinzhang7234

轉自: http://bdx66.top/?thread-38.htm

HashMap和ConcurrentHashMap 源碼關鍵點解析