在java中Map中的實現有HashMap、HashTable、LinkedHashMap等,其中最常用的有HashMap和HashTable,那么HashMap為什么很常用呢?因為HashMap的效率更高些,如果不是在多線程的環境下,不考慮線程安全問題,HashMap絕對是首選項,HashMap通過計算hash值實現快速查找的功能,所以查找的效率特別的高,那么HashMap的結構是什么樣子的呢?

HashMap就是這種數組加上鏈表的結構使得查詢的速度非常快,也是通過鏈表的方式解決了hash沖突問題,但是如果通過hash算法得到的值總是同一個那么鏈表就會非常的長,或者是每次計算的hash的值都不一樣,為了解決這些問題問題,在JDK8中,HashMap使用紅黑樹的數據結構取代了鏈表機構。

當然也說到了,hashMap會出現線程安全問題,那么誰是線程安全的呢?HashTable是線程安全的,因為hashTable底層使用了synchronized關鍵字,保證了線程安全問題,但是如果一個線程訪HashTable的同步方法時,其它線程也來訪問,那么只能進入阻塞或是輪詢狀態,所以效率非常的低下。那么有沒有既線程安全有速度快的Map呢,當然有了,ConcurrentHashMap就是這樣的Map,hashTable之所以慢的原因是所有訪問HashTable的線程都必須競爭一把鎖,無論訪問hashTable中的哪些數據都是競爭一把鎖,ConcurrentHashMap的巧妙之處就在於把數據分成很多部分,每一部分加一把鎖,每個線程訪問的數據不同,線程之間就不會存在競爭同一把鎖的情況,這就是ConcurrentHashMap的分段鎖,既給數據加了鎖,保證了數據的安全性,也減少了鎖的競爭,提高了性能,那么ConcurrentHashMap的結構又是什么樣的呢?

如圖所示,ConcurrentHashMap是由Segment數組和hashEntry數組組成,Segment是一種可重入鎖,hashEntry則是用來存放鍵值對的數據的,在每一個ConcurrentHashMap中都包含一個Segment數組,Segment的結構則是類似hashMap的結構,是數組加鏈表的結構,每一個Segment里都包含一個HashEntry數組,當線程想要處理hashEntry中的數據時,首先要先獲得該hashEntry的Segment鎖,這樣就保證了ConcurrentHashMap中hashEntry里的數據的安全問題,因此ConcurrentHashMap比hashTable的效率更高,比HashMap更加安全,當你既要考慮安全問題又要考慮性能問題時,ConcurrentHashMap是一個不錯的選擇。