簡單分析HashMap及其執行緒安全的Map類

2021-08-07 05:26:43 字數 2993 閱讀 7749

基於雜湊表的 map 介面的實現。此實現提供所有可選的對映操作,並允許使用 null 值和 null 鍵。(除了非同步和允許使用 null 之外,hashmap 類與 hashtable 大致相同。)此類不保證對映的順序,特別是它不保證該順序恆久不變。 此實現假定雜湊函式將元素適當地分布在各桶之間,可為基本操作(get 和 put)提供穩定的效能。迭代 collection 檢視所需的時間與 hashmap 例項的「容量」(桶的數量)及其大小(鍵-值對映關係數)成比例。所以,如果迭代效能很重要,則不要將初始容量設定得太高(或將載入因子設定得太低)。

mapmap = new hashmap<>();

map.get("");

map.put("",null);

map.clear();

map.isempty();

...

類實現乙個雜湊表,該雜湊表將鍵對映到相應的值。任何非 null 物件都可以用作鍵或值。為了成功地在雜湊表中儲存和獲取物件,用作鍵的物件必須實現 hashcode 方法和 equals 方法。

mapmap = new hashtable<>();

map.get("");

map.put("",null);

map.clear();

map.isempty();

...

concurrenthashmap繼承abstractmap,實現了concurrentmap介面。同時concurrentmap介面繼承map介面。

簡單來說,concurrenthashmap屬於解決併發情況下的類。擁有hashtable和hashmap的優勢。

mapmap = new concurrenthashmap<>();

map.get("");

map.put("",null);

map.clear();

map.isempty();

...

咋一看hashmap、hashtable、concurrenthashmap用法幾乎一致,畢竟都是實現了map介面,日常使用的也就是map介面的方法。

重點就是它們各自對實現map介面具有差異。

下面我們以map的put方法簡單敘述一下它們的執行緒安全性

hashmap

public v put(k key, v value) 

......

if ((p = tab[i = (n - 1) & hash]) == null)

tab[i] = newnode(hash, key, value, null);

else

......

node(int hash, k key, v value, nodenext)

當hashmap執行put時,會走

tab[i] = newnode(hash, key, value, null);
為map建立乙個新的node節點。節點的hash值是根據key的值計算出來的。node為hashmap的乙個內部類——內部實體物件。乙個put的操作背後是有多個執行緒一起進行操作的。底層有乙個cache,jvm是先把具體的key和value放在快取的entry中,entry是乙個單鏈。node就和這個單鏈上的結點一一對應起來。這麼看下來,難怪說是效能好,執行緒不安全,光這麼乙個put操作,沒有看到任何執行緒安全操作的步驟啊。多執行緒同時操作這個put方法,在entry這個單鏈中,誰能保證下乙個結點儲存的是乙個正確的資料。

hashtable

public

synchronized v put(k key, v value)

// makes sure the key is not already in the hashtable.

entry,?> tab = table;

int hash = key.hashcode();

int index = (hash & 0x7fffffff) % tab.length;

@suppresswarnings("unchecked")

entryentry = (entry)tab[index];

for(; entry != null ; entry = entry.next)

}addentry(hash, key, value, index);

return

null;

}

此時hashtable原始碼一貼,立馬清晰可見,put方法上加了乙個synchronized,這不就是乙個同步**塊麼。具體**不用分析,大家也就知道了,哦哦~~這個put方法被synchronized修飾了,是執行緒安全的,多執行緒同時執行它,方法是乙個乙個一次執行的,不會出現任何問題。但是這樣也帶來了乙個弊端,效能效率太慢了。。。

如何可以看到hashmap的執行結果永遠是不會正確的,就是因為它在put時,node所對應的entry中的hash被衝撞掉了。其他兩種map都是安全的,結果都是正確的。不過現如今已經不推薦使用hashtable了,如果要使用安全的map,就用concurrenthashmap。

HashMap原始碼簡單分析

1 還是老習慣,一邊看,一邊新增注釋,希望堅持下去,hashmap的基本原始碼進行了分析,內部一些介面和設計還沒來得及看23 一 成員 45 1 transient entry table 67 hashmap內部維護了乙個內部類 entry,用來存放鍵值對,這個entry實現了map.entry這...

HashMap 底層分析

更多 hashmap 與 concurrenthashmap 相關請檢視這裡。以下基於 jdk1.7 分析。如圖所示,hashmap 底層是基於陣列和鍊錶實現的。其中有兩個重要的引數 容量的預設大小是 16,負載因子是 0.75,當hashmap的size 16 0.75時就會發生擴容 容量和負載因...

HashMap 底層分析

以下基於 jdk1.7 分析。hashmap 底層是基於陣列和鍊錶實現的。其中有兩個重要的引數 容量的預設大小是 16,負載因子是 0.75,當hashmap的size 16 0.75時就會發生擴容 容量和負載因子都可以自由調整 首先會將傳入的 key 做hash運算計算出 hashcode,然後根...