TreeMap
文章開頭,全家桶少不了。
作為HashMap的好兄弟,TreeMap存在肯定是有的他的理由的。
我看源碼喜歡先看JavaDoc
翻譯TreeMap的JavaDoc
基于紅黑樹的NavigableMap實現。 根據映射的鍵的Comparable或根據映射創建時提供的Comparator對映射進行排序,具體取決于所使用的構造函數。
此實現為containsKey,get,put和remove操作提供了保證的log(n)時間成本。算法是對Cormen,Leiserson和Rivest的<<算法簡介>>中的算法的改編。
請注意,與任何已排序的映射一樣,樹映射所維護的順序以及是否提供顯式比較器,必須與equals是正確的實現Map接口。具體請參見Comparable或Comparator,以精確了解與equals一致的。之所以這樣,是因為Map接口是根據equals操作的,但是排序的映射使用其compareTo或compare方法執行所有鍵比較,此方法視為相等的兩個鍵是排序后的Map。排序后的映射的行為是明確定義的,即使其順序與equals不匹配;它只是無法遵守Map接口的一般合同。
查看TreeMap的繼承圖
也就是說所有基本的CRUD操作其實都是和Map一樣的,所以就不詳細寫了,主要還是寫一些這個的應用場景以及使用的注意點,以及他的特點。
首先TreeMap是基于紅黑樹來實現的,那就順帶復習一下紅黑樹好了。
紅黑樹規則特點:
節點分為紅色或者黑色;
根節點必為黑色;
葉子節點都為黑色,且為null;
連接紅色節點的兩個子節點都為黑色(紅黑樹不會出現相鄰的紅色節點);
從任意節點出發,到其每個葉子節點的路徑中包含相同數量的黑色節點;
新加入到紅黑樹的節點為紅色節點;
紅黑樹自平衡基本操作:
變色:在不違反上述紅黑樹規則特點情況下,將紅黑樹某個node節點顏色由紅變黑,或者由黑變紅;
左旋:逆時針旋轉兩個節點,讓一個節點被其右子節點取代,而該節點成為右子節點的左子節點
右旋:順時針旋轉兩個節點,讓一個節點被其左子節點取代,而該節點成為左子節點的右子節點
TreeMap的特點:
TreeMap實現了NavigableMap接口,而NavigableMap接口繼承著SortedMap接口,致使我們的TreeMap是有序的!如果沒有實現comparator,默認按照key的自然順序排序。如果在構造方法中傳遞了Comparator對象,那么就會按照Comparator的方法進行比較值得說明的是:如果使用的是compareTo(T o)方法來比較,key一定是不能為null,并且得實現了Comparable接口的。即使是傳入了Comparator對象,不用compareTo(T o)方法來比較,key也是不能為null的
由于底層是紅黑樹,那么時間復雜度可以保證為log(n)這個理論的介紹可以看https://blog.csdn.net/JERRY_PRI/article/details/8959426?utm_source=blogxgwz1
key不能為null,為null為拋出NullPointException的,但是如果硬要為null就是在構造的時候用自己的Comparator
想要自定義比較,在構造方法中傳入Comparator對象,否則使用key的自然排序來進行比較
TreeMap非同步的,想要同步可以使用Collections來進行封裝
TreeMap的使用場景:
這其實也認為是紅黑樹的使用場景
紅黑樹是犧牲了嚴格的高度平衡的優越條件為代價,它只要求部分地達到平衡要求,降低了對旋轉的要求,從而提高了性能。
紅黑樹能夠以O(log2 n)的時間復雜度進行搜索、插入、刪除操作。此外,由于它的設計,任何不平衡都會在三次旋轉之內解決。當然,還有一些更好的,但實現起來更復雜的數據結構能夠做到一步旋轉之內達到平衡,但紅黑樹能夠給我們一個比較“便宜”的解決方案。
TreeMap 實現了 SortMap 接口,其能夠根據鍵排序,默認是按鍵的升序排序,也可以指定排序的比較器,當用 Iterator 遍歷 TreeMap 時得到的記錄是排過序的,TreeMap 取出來的是排序后的鍵值
紅黑樹占用的內存更小(僅需要為其存在的節點分配內存),而Hash事先應該分配足夠的內存存儲散列表,即使有些槽可能棄用。
TreeMap的注意點:
紅黑樹是以 key 來進行排序的,所以這里以 key 來進行比較檢索出合適的葉子結點,而比較多依據就是 Comparator 或者 Comparable ,如果比較出來的結果是 0,那么后面的 value 會覆蓋前面的 value。所以在使用 Map 的時候,一定要注意底層的數據結構和對 key 的處理方式。
總結
- 上一篇: 【H2 Database】导出CSV
- 下一篇: 对嗓子有好处的水果