HashMap的幾個要點

HashMap的幾個要點:

1、數據存儲的底層數據結構

2、擴容機制 與rehash

3、同步問題(HashMap HashTable ConcurrentHashMap的區別與理解)

 

一、數據結構與存儲

1、HashMap底層是通過數組+鏈表的數據結構實現的。

 

2、整體來看hashMap中所有數據都存於一個數組table中,數組中的每個元素又是一個鏈表(hash值相同的元素會被放到一個鏈表中),鏈表中的每個節點存入的是每次put進去的元素(put進去的元素會被包裝成Node節點)。

 

3、在put元素obj時,會根據元素obj的key的hash值,計算其應該被放在數組哪個位置,即數組的下標i(計算方法,i=hash值%數組的長度,算出的餘數就是下標i)

3.1、計算出下標i後,看數組中table[i]是爲空,若爲空,則直接讓將obj包裝成一個Node節點,賦值給table[i](table[i]=new Node(obj) 代碼僅作示意);不爲空則,則依次比較table[i]這個鏈表每個元素的val,若相等,則覆蓋。若都不相等,則放到鏈表的最後。

 

4、爲了解決極端情況的hash衝突,jdk1.8引入了紅黑樹數據結構。當table[i]中的鏈表節點數大於8時,會將鏈表轉成紅黑樹進行存儲。當節點數小於6時,則會轉成鏈表儲存。

 

擴展閱讀 https://blog.csdn.net/Dr_Joker/article/details/57101211

 

 

二、擴容機制 與rehash

擴容機制。hashMap中有全負載因子爲0.75。當HashMap的size大於等於 table.length*0.75時,會進行擴容。將重新創建一個newTable來進行存儲。newTable的length爲table.length*2;  擴容後需要進行rehash。

 

rehash

1、新建一個hash桶newTable,size是原hash桶oldTable的兩倍。

2、遍歷oldTable中的每個元素,重新計算其hash值,並將其放入到newTable中

       2、1 遍歷oldTable中的每個元素,(這裏的每個元素是鏈表)

       2、1、1 將鏈表中的頭節點取出,暫存於e中,並將該鏈表在oldTable中的位置置空。

       2、1、2 取出e.next元素,暫存於next中

       2、1、3 對e進行計算,算出其在newTable中的位置的下標。

       2、1、4 計算出下標後,根據下標,將e元素放入到newTable中(newTable的每個元素是鏈表,是將e放入到鏈表的頭節點)

       2、1、4 將next賦值於e,進行while循環。

擴展閱讀 https://blog.csdn.net/longwoniu/article/details/48781777

 

 

三、同步問題

HashMap是線程不安全的。解決線程不安全的問題有三:

1、HashTable

2、Collections. synchronizedMap(Map)

3、ConcurrentHashMap

 

1和2都是有Map的每個方法上加上了synchronized關鍵字,以此來保證線程安全

3 創新點在於對Map進行分段加鎖,分成16段分別加鎖,所以支持16個線程同時進行寫操作。在讀的時候不受限制。

擴展閱讀 https://yemengying.com/2016/05/07/threadsafe-hashmap/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章