淺談hashmap

? ? ? ? 學習了java這么久沒有看過hashmap源碼,近期才來了解hashmap的底層結構,雖然網上有很多關于hashmap的文章但是我還是想學習總結一下。

? ? ? ? 在jdk1.8之前hashmap是數組+鏈表的形式,jdk1.8變成了數組+鏈表+紅黑樹的結構,核心都是為了提高查詢速度,現在聊下hashmap的數據結構基于jdk1.8。

基礎結構圖
node類

node對象屬性

hash:key的哈希值

key:節點的key,類型和定義HashMap時的key相同

value:節點的value,類型和定義HashMap時的value相同

next:該節點的下一節點

????????當它第一次put時候,它才會進行初始化擴容默認大小capacity是16第二次是32第三次是64就算設置初始化20,大小也是32,每次擴容都是2的冪,之所以每次擴容都為2的冪是為了符合Hash算法均勻分布的原則,防止取模運算后有些index結果的出現幾率會更大,而有些index結果永遠不會出現,為了index分布的更加均勻,所以采取2的冪。可以參考hashmap

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

? ? ? ?而且hashmap還有個負載因子loadFactor(默認0.75)、capacity容量大小(默認16)和threshold(loadFactor * capacity),這個負載因子主要是用來衡量HashMap滿的程度,它主要是設置一個界限,當map的容量除以capacity總容量大小>=loadFactor,其實就是map當前容量大于threshold將會進行擴容。

put方法

? ? ? ? 如果當鏈表的節點的長度大于TREEIFY_THRESHOLD(默認是8,雖然判斷是bincont>=7但是由于for循環是給p.next進行賦值,所以當bincont為7的時候他的鏈表長度已經是8了)的時候將會轉成紅黑樹,但是如果tab長度小于MIN_TREEIFY_CAPACITY(默認值是64),它不會轉紅黑樹而是將進行擴容再次散列((n -1) & hash取模,因為擴容后長度變動,重新散列后node下標會變動達到防止鏈表過長的目的)避免鏈表過長。


鏈表轉紅黑樹《

????????因為hashmap是非線程安全的,如果多線程操作hashmap擴容時可能會發生死鎖的問題,假設我們有兩個線程A、B,hashmap容量為2,A線程放入key T1、T2、T3、T4、T5,同時T1、T2和T3的hash值相同,形成一個鏈表T1->T2->T3,而T4、T5hash值不相同,于是這時候容量不足,需要進行擴容(rehash),于是新建一個更大容量的hash表,將數據從老的hash表中進行遷移,這時候B線程進來了,A線程掛起,這時候B線程發現容量不足也需要擴容,這時候線程B擴容的之后的鏈表為T1->T2,然后B線程執行完了,A線程繼續執行,將鏈表變成了T2->T1,這時候形成了T1.next=T2,T2.next=T1,所以當用戶對這個key進行取值的時候將會陷入死循環卡在那沒有反應。

? ? ? ? 如果需要多線程操作hashmap可以使用ConcurrenHashmap進行替代,ConcurrenHashmap是一個線程安全的hashtable,這時候就有人問為什么不直接使用hashtable,雖然hashtable也是線程安全的但是hashtable鎖定的是一整個hash表,效率較為低下,而ConcurrenHashmap可以做到讀取數據不進行加鎖實現段鎖,因為其內部結構有個Segment的存在,使其進行寫操作的時候可以將鎖的粒度保持盡量小。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,238評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,430評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,134評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,893評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,653評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,136評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,212評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,372評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,888評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,738評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,939評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,482評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,179評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,588評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,829評論 1 283
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,610評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,916評論 2 372