HashMap和CurrentHashMap及HashTable的區別

HashMap原理請看https://blog.csdn.net/qq_17021569/article/details/102519163

HashMap

CurrentHashMap和HashMap的主要區別在數組那裏

(1)ConcurrentHashMap對整個桶數組進行了分段,HashMap沒有

(2)ConcurrentHashMap在每一個分段上都用鎖進行保護,從而讓鎖的粒度更精細一些,併發性能更好,而HashMap沒有鎖機制,不是線程安全的

               CurrentHashMap                                                           HashMap

 

ConcurrentHashMap的併發度是什麼

ConcurrentHashMap的併發度就是segment的大小,默認爲16,這意味着最多同時可以有16條線程操作ConcurrentHashMap,這也是ConcurrentHashMap對Hashtable的最大優勢

HashMap在Java1.7與1.8中的區別:

JDK1.7中使用一個Entry數組來存儲數據,用key的hashcode取模來決定key會被放到數組裏的位置,如果hashcode相同,或者hashcode取模後的結果相同(hash collision),那麼這些key會被定位到Entry數組的同一個格子裏,這些key會形成一個鏈表。在hashcode特別差的情況下,比方說所有key的hashcode都相同,這個鏈表可能會很長,那麼put/get操作都可能需要遍歷這個鏈表。也就是說時間複雜度在最差情況下會退化到O(n)

JDK1.8中使用一個Node數組來存儲數據,但這個Node可能是鏈表結構,也可能是紅黑樹結構。如果插入的key的hashcode相同,那麼這些key也會被定位到Node數組的同一個格子裏。如果同一個格子裏的key不超過8個,使用鏈表結構存儲。如果超過了8個,那麼會調用treeifyBin函數,將鏈表轉換爲紅黑樹。那麼即使hashcode完全相同,由於紅黑樹的特點,查找某個特定元素,也只需要O(log n)的開銷。也就是說put/get的操作的時間複雜度最差只有O(log n)。

ConcurrentHashMap在Java1.7與1.8中的區別:

ConcurrentHashMap在jdk1.7中採用Segment + HashEntry的方式進行實現;1.8中放棄了Segment臃腫的設計,取而代之的是採用Node + CAS + Synchronized來保證併發安全進行實現

HashTable

  • 底層數組+鏈表實現,無論key還是value都不能爲null線程安全實現線程安全的方式是在修改數據時鎖住整個HashTable,效率低,ConcurrentHashMap做了相關優化
  • 初始size爲11,擴容:newsize = olesize*2+1
  • 計算index的方法:index = (hash & 0x7FFFFFFF) % tab.lengt

HashMap

  • 底層數組+鏈表實現,可以存儲null鍵和null值,線程不安全
  • 初始size爲16,擴容:newsize = oldsize*2,size一定爲2的n次冪
  • 擴容針對整個Map,每次擴容時,原來數組中的元素依次重新計算存放位置,並重新插入
  • 插入元素後才判斷該不該擴容,有可能無效擴容(插入後如果擴容,如果沒有再次插入,就會產生無效擴容)
  • 當Map中元素總數超過Entry數組的75%,觸發擴容操作,爲了減少鏈表長度,元素分配更均勻
  • 計算index方法:index = hash & (tab.length – 1)

ConcurrentHashMap

  • 底層採用分段的數組+鏈表實現,線程安全
  • 通過把整個Map分爲N個Segment,可以提供相同的線程安全,但是效率提升N倍,默認提升16倍。(讀操作不加鎖,由於HashEntry的value變量是 volatile的,也能保證讀取到最新的值。)
  • Hashtable的synchronized是針對整張Hash表的,即每次鎖住整張表讓線程獨佔,ConcurrentHashMap允許多個修改操作併發進行,其關鍵在於使用了鎖分離技術
  • 有些方法需要跨段,比如size()和containsValue(),它們可能需要鎖定整個表而而不僅僅是某個段,這需要按順序鎖定所有段,操作完畢後,又按順序釋放所有段的鎖
  • 擴容:段內擴容(段內元素超過該段對應Entry數組長度的75%觸發擴容,不會對整個Map進行擴容),插入前檢測需不需要擴容,有效避免無效擴容

Hashtable和HashMap都實現了Map接口,但是Hashtable的實現是基於Dictionary抽象類的

 

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