HashMap(數組+鏈表+紅黑樹)、HashTable、TreeMap


  HashMap根據鍵的hashCode值存儲數據,大多數情況下可以直接定位到它的值,因而具有很快的訪問速度,但遍歷順序卻不是確定的,HashMap最多只允許一條記錄的鍵為null,允許多條記錄的值為null,HashMap非線程安全,即任一時刻可以有多個線程同時寫HashMap,可能會導致數據的不一致,如果需要滿足線程安全,可以用Collections的synchronizedMap方法使HashMap具有線程安全的能力,或者使用ConcurrentHashMap。大方向上,HashMap 是一個數組,然后數組中每個元素是一個單向鏈表,很多實體都是嵌套類Entry的實例,Entry包含四個屬性:key、value、hash值和用於單向鏈表的next。

圖為 Java 7中HashMap的結構

  1. capacity:當前數組容量,始終保持 2^n,可以擴容,擴容后數組大小為當前的 2 倍。
  2.  loadFactor:負載因子,默認為 0.75。 
  3. threshold:擴容的閾值,等於 capacity * loadFactor。

  上面是Java 7 對HashMap的實現,在JAVA 8中,利用了紅黑樹,所以在JAVA 8 是由數組+鏈表+紅黑樹組成。從JAVA 7中得知,在查找元素時候,可以根據hash值快速定位到數組具體的下標,但是后面的操作需要順着鏈表一個一個的比較下去才能找到所需值,時間復雜度取決於鏈表的長度,為O(n),為了降低這一部分處理的開銷,在JAVA 8中,當鏈表中的元素超過8個之后,會將鏈表轉換為紅黑樹,在這些位置進行查找的時候可降低時間復雜度 為O(logn),

圖為 JAVA 8中HashMap的結構

  HashTable是一個線程安全的遺留類,很多映射的功能跟HashMap類似,不同的是它繼承Dictionary類,並且是線程安全的,任一時間只有一個線程可寫HashTable,並發行不好,可以在不需要線程安全的時候替換為HashMap,需要線程安全的時候可以用ConcurrentHashMap替換。

  TreeMap可排序,實現了SortedMap接口,可以把它保存的記錄根據鍵排序,它默認是按鍵的升序排序,可以指定排序的比較器,當用迭代器(Iterator)遍歷TreeMap時,得到的記錄是排序過的。

在使用 TreeMap 時,key 必須實現 Comparable 接口或者在構造 TreeMap 傳入自定義的 Comparator,否則會在運行時拋出java.lang.ClassCastException類型的異常。 參考:https://www.ibm.com/developerworks/cn/java/j-lo-tree/index.html,寫的很好這個。

 

LinkedHashMap 是 HashMap 的一個子類,保存了記錄的插入順序,在用 Iterator 遍歷 LinkedHashMap時,先得到的記錄肯定是先插入的,也可以在構造時帶參數,按照訪問次序排序。

參考1:http://www.importnew.com/28263.html
參考2:http://www.importnew.com/20386.html#comment-648123


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM