HashMap
HashMap的數據結構
是由數組加鏈表的方式組成,有快速查找修改和方便增加刪除的優(yōu)勢胎源。結構圖如下所示
HashMap的存放過程
通過hash算法得到hashCode掸哑,根據hashCode來確定數組的索引,存到鏈表中品山。存入會有三個可能:
1.索引位置為空友酱,直接放入。
2.索引位置不為空劫谅,鏈表中有相同的key值见坑,找到替換value即可嚷掠。
3.索引位置不為空捏检,鏈表中沒有相同的key值荞驴,則將該實例插到鏈表頭部。Java8中當長度超過8時贯城,會變成紅黑樹的方式存儲熊楼。
HashMap的查找過程
首先根據hashCode找到數組索引,然后在鏈表中根據key找到value值能犯。整個查找過程的時間復雜度取決于存放過程是否均勻分布在每個數組中也就是hash算法鲫骗。理論上時間復雜度為o(1)。
HashMap的擴容
默認的HashMap的長度是16踩晶,負載因子為0.75执泰。當HashMap中的數量大于閾值(長度*負載因子),HashMap會進行擴容渡蜻,長度變?yōu)樵瓉淼膬杀妒趿摺Mㄟ^rehash,得到新的hashcode將元素從舊表移動到新表中茸苇。擴容轉移過程中:
1.發(fā)生hash沖突時排苍,Java7會在鏈表頭部插入,Java8會在鏈表尾部插入
2.擴容后轉移數據学密,Java7轉移前后鏈表順序會倒置淘衙,Java8還是保持原來的順序
3.關于性能對比,引入紅黑樹的Java8大程度得優(yōu)化了HashMap的性能
HashMap線程不安全
HashMap是線程不安全的腻暮,容易造成死循環(huán)(Java7)和數據不一致的問題彤守。
ConcurrentHashMap
ConcurrentHashMap結構
總結一下:帶鎖的HashMap數組,具體的hashEntry可以形成鏈表哭靖。
Segment數組S[]長度 =2的n次方(2的n次方 >= concurrencyLevel)遗增,默認concurrencyLevel = 16,根據公式Segment長度為16款青。concurrentcyLevel可以根據構造函數ConcurrentHashMap(int initialCapacity,float loadFactor, int concurrencyLevel)來賦值做修。默認S[0]中table長度為2。
ConcurrentHashMap是線程安全
有人會問HashTable也是線程安全的抡草,兩者有什么區(qū)別:
- HashTable是對put這個操作加鎖饰及,這會存在一個問題,就是當一個線程put操作特別長就會出現(xiàn)等待問題康震,沒有效率燎含。
-
ConcurrentHashMap只是鎖住segments數組的某個位置,而不是整個腿短,當另一個線程不是進入該位置時屏箍,就可以同時操作绘梦。
什么是HashMap?
高并發(fā)下的HashMap
什么是ConcurrentHashMap
淺談HashMap與線程安全 (JDK1.8)