斷斷續續寫了半個月,今天終於把TreeMap
容器中的紅黑樹
搞定了,現在來水一篇又快又短
的Java Map容器
總結博客 😂😂。
註明:本篇博客不會涉及容器的源碼什麼的,主要是總結各個map
容器的底層實現特點、主要運用場景。如果你需要詳細瞭解更多關於Java
中的map
容器實現的細節,文末會提供我前面寫的源碼分析的博客鏈接,歡迎閱讀。
Java中的常見五種map容器源碼分析總結目錄
一、Java
中的Map
容器概述
Map
是一種存儲key-value
(鍵值對
)的容器,在Java中,常見的Map
接口的實現類有五種,分別是HashMap
、Hashtable
、ConcurrentHashMap
、LinkedHashMap
、TreeMap
。五種容器的關係如下圖:
順帶一提,貌似有不少人覺得map
就是hashmap
、hashmap
就是map
,把hash
與map
兩個概念混爲一談。然而map
是用於存儲key-value
的虛擬容器,按照key的hash值將節點散列到一個table數組
(也稱hash表
)的table[i]
(也稱hash桶
)中。等你看完TreeMap
的底層數據結構就會發現,不通過key.hash值
,也可以實現map容器
。
二、HashMap
容器
1、HashMap
概述
Java中的HashMap
底層使用一個table數組
存放節點,使用鏈表(JDK 1.8
新增紅黑樹
)解決hash衝突
(多個元素的hash值
散列到同一個table[i]
中)的問題。
2、HashMap
數據結構示意圖
3、HashMap
特點
- ①、存取高效,不支持併發讀寫操作(沒有引入鎖任何機制)
- ②、table數組的長默認是16,並且每次擴容爲原來的2倍(長度總是保持爲2的次冪,方便hash值求餘)
- ③、支持key、value爲null的鍵值對插入
4、HashMap
源碼分析鏈接
Java容器之HashMap源碼分析(媽媽再也不用擔心我不懂HashMap了)
三、Hashtable
容器
1、Hashtable
概述
Java中的Hashtable
底層同樣是使用一個table數組
存放節點,使用鏈表解決hash衝突
(多個元素的hash值
散列到同一個table[i]
中)的問題。不過引入了鎖機制
(通過synchronized關鍵字,鎖爲this,每次鎖住整個容器),支持併發操作。
2、Hashtable
數據結構示意圖
3、Hashtable
特點
- ①、寫入、刪除效率相對較低。引入鎖機制,通過synchronized關鍵字修飾方法(同步方法),鎖對象爲this,每次鎖住整個容器,鎖的粒度太大。
- ②、table數組的長默認是11,並且每次擴容爲原來的2倍 + 1
- ③、不支持key、value爲null的鍵值對插入
4、Hashtable
源碼分析鏈接
Java容器之Hashtable源碼分析(關於Hashtable的這些細節你可能還不知道)
四、ConcurrentHashMap
容器
1、ConcurrentHashMap
概述
Java中的ConcurrentHashMap
底層同樣是使用一個table數組
存放節點,使用鏈表解決hash衝突
(多個元素的hash值
散列到同一個table[i]
中)的問題。在JDK 1.8前的版本中引入段的概念,使用RententLock
鎖,並且分段鎖(對每個段分別設置一個鎖),相比於Hashtable鎖整個容器,併發操作時,效率提高了不少。
在JDK 1.8
的時候,又取消了段的概念,重新使用synchronized
關鍵字(同步代碼塊)。不過每次鎖住的對象的是需要修改的table[i]
(hash桶
),並且在各大方法中儘量減少了同步代碼塊中的代碼量,從而減少了鎖的粒度,併發操作時,效率提高了不少。在擴容時,支持多個線程同時進行擴容(併發擴容)。
2、ConcurrentHashMap
數據結構示意圖
3、ConcurrentHashMap
特點
- ①、寫入、刪除效率相比與Hashtable容器較高。引入鎖機制,通過synchronized關鍵字(同步代碼塊),鎖對象爲即將修改的table[i](hash桶),鎖的粒度小。
- ②、table數組的長默認是16,並且每次擴容爲原來的2倍(長度總是保持爲2的次冪,方便hash值求餘)
- ③、不支持key、value爲null的鍵值對插入
4、ConcurrentHashMap
源碼分析鏈接
Java容器之ConcurrentHashMap源碼分析(JDK 1.7與JDK 1.8對比)
五、LinkedHashMap
容器
1、LinkedHashMap
概述
Java中的LinkedHashMap
是HashMap
的子類,也可以說是對HashMap
的封裝。對外展示的是一個雙向鏈表
,鏈表中的元素順序,就是插入節點的順序。
2、LinkedHashMap
數據結構示意圖
3、LinkedHashMap
特點
- ①、LinkedHashMap是對HashMap的進一步封裝,所以實現細節基本一致
- ②、對外展示爲雙向鏈表,鏈表節點中的順序爲插入時的順序(其實也可以修改爲訪問順序)
4、LinkedHashMap
源碼分析鏈接
Java容器之LinkedHashMap源碼分析(看看確定不點進來?進來真不點?)
六、TreeMap
容器
1、TreeMap
概述
Java中的TreeMap
容器底層是通過維護一棵紅黑樹來存儲key-value
節點,與hash沒有任何關係。樹中的節點按照key
的大小排序,可以手動指定key的比較器comparator
。
2、TreeMap
數據結構示意圖
3、TreeMap
特點
- ①、讀寫高效,查找的複雜度在O(log2n)級別。(不支持併發讀寫,爲引入鎖)
- ②、節點按照key升序排列,可指定key的比較器comparator
- ③、不支持key爲null的key-value插入
4、TreeMap
源碼分析鏈接
七、總結
HashMap
、LinkedHashMap
、Hashtable
、ConcurrentHashMap
這四個都是通過table數組,並結合hash散列存放節點,前兩者不支持併發讀寫,效率較高,後兩者支持併發,並且ConcurrentHashMap
的效率更高些。TreeMap
容器通過紅黑樹存儲key-value
節點,節點按照key的大小排序,查找、插入比較高效,時間複雜度在O(log2n)級別。