HashMap的幾個要點

2021-09-27 01:16:49 字數 1449 閱讀 8494

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時,則會轉成鍊錶儲存。

擴充套件閱讀 

擴容機制。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迴圈。

擴充套件閱讀 

hashmap是執行緒不安全的。解決執行緒不安全的問題有三:

1、hashtable

2、collections. synchronizedmap(map)

3、concurrenthashmap

1和2都是有map的每個方法上加上了synchronized關鍵字,以此來保證執行緒安全

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

擴充套件閱讀 

使用STL的hash map要點

說來慚愧,使用了很久visual stdio 2003了,只知道mfc公升級到了7.0,atl也公升級到了7.0,對於這兩個經典的類庫做了一些研究,但一直沒有注意c 標準庫的變化。今天嘗試的使用了stdext hash map這個庫,果然不錯。下面寫下一些心得。hash map類在標頭檔案hash ...

使用STL的hash map要點

使用了很久visual stdio 2003了,只知道mfc公升級到了7.0,atl也公升級到了7.0,對於這兩個經典的類庫做了一些研究,但一直沒有注意c 標準庫的變化。今天嘗試的使用了stdext hash map這個庫,果然不錯。下面寫下一些心得。hash map類在標頭檔案hash map中,...

Hashmap排序的幾個方法

假設有這樣的類 如下 示例 class student public string tostring hashmap map newhashmap map.put 1003 new student 1003 sam map.put 1005 new student 1005 joseph map.p...