Java集合框架:TreeMap
歡迎支持筆者新作:《深入理解Kafka:核心設(shè)計(jì)與實(shí)踐原理》和《RabbitMQ實(shí)戰(zhàn)指南》,同時(shí)歡迎關(guān)注筆者的微信公眾號:朱小廝的博客。
歡迎跳轉(zhuǎn)到本文的原文鏈接:https://honeypps.com/java/java-collection-treemap/
TreeMap定義
package java.util; public class TreeMap<K,V>extends AbstractMap<K,V>implements NavigableMap<K,V>, Cloneable, java.io.Serializable{ } public interface NavigableMap<K,V> extends SortedMap<K,V>{}??TreeMap繼承AbstractMap,實(shí)現(xiàn)NavigableMap、Cloneable、Serializable三個(gè)接口。其中AbstractMap表明TreeMap為一個(gè)Map即支持key-value的集合, NavigableMap則意味著它支持一系列的導(dǎo)航方法,具備針對給定搜索目標(biāo)返回最接近匹配項(xiàng)的導(dǎo)航方法 。
??TreeMap中同時(shí)也包含了如下幾個(gè)重要的屬性:
//比較器,因?yàn)門reeMap是有序的,通過comparator接口我們可以對TreeMap的內(nèi)部排序進(jìn)行精密的控制
private final Comparator<? super K> comparator;
//TreeMap紅-黑節(jié)點(diǎn),為TreeMap的內(nèi)部類
private transient Entry<K,V> root = null;
//容器大小
private transient int size = 0;
//TreeMap修改次數(shù)
private transient int modCount = 0;
//紅黑樹的節(jié)點(diǎn)顏色–紅色
private static final boolean RED = false;
//紅黑樹的節(jié)點(diǎn)顏色–黑色
private static final boolean BLACK = true;
??對于實(shí)體節(jié)點(diǎn)Entry是TreeMap的內(nèi)部類,它有幾個(gè)重要的屬性:
//鍵
K key;
//值
V value;
//左孩子
Entry<K,V> left = null;
//右孩子
Entry<K,V> right = null;
//父親
Entry<K,V> parent;
//顏色
boolean color = BLACK;
??關(guān)于紅黑樹的實(shí)現(xiàn)可以搜索一些相關(guān)資料,我覺得參考資料3就不錯(cuò),博主就不贅述了。
TreeMap特點(diǎn)
可以采用這種方式將TreeMap設(shè)置為同步的:Map m = Collections.synchronizedSortedMap(new TreeMap(…));
TreeMap是SortedMap接口的基于紅黑樹的實(shí)現(xiàn)。此類保證了映射按照升序順序排列關(guān)鍵字, 根據(jù)使用的構(gòu)造方法不同,可能會(huì)按照鍵的類的自然順序進(jìn)行排序,或者按照創(chuàng)建時(shí)所提供的比較器(自定義)進(jìn)行排序。
先舉個(gè)案例說明一下:
??輸出結(jié)果:
1:null 2:3 3:2 10:1??也可以采用自定義的類,引用《Comparable與Comparator淺析》中的Person1舉例:
public class Person1 implements Comparable<Person1> {private int age;private String name;public Person1(String name, int age){this.name = name;this.age = age;}@Overridepublic int compareTo(Person1 o){return this.age-o.age;}@Override public String toString(){return name+":"+age;} }?? 測試代碼:
Map<Person1,Integer> map = new TreeMap<>();Person1 person1 = new Person1("zzh",18);Person1 person2 = new Person1("jj",17);Person1 person3 = new Person1("qq",19);map.put(person1, 1);map.put(person2, 2);map.put(person3, 3);for(Entry<Person1, Integer> entry:map.entrySet()){System.out.println(entry.getKey()+":"+entry.getValue());}??測試結(jié)果:
jj:17:2 zzh:18:1 qq:19:3??只要自定義鍵的類實(shí)現(xiàn)了Comparable接口就可以使用TreeMap的排序功能,也可以通過Comparator接口實(shí)現(xiàn)(關(guān)于Comparable和Comparator的區(qū)別可以翻看《Comparable與Comparator淺析》),如下:
??首先引用類Person2:
??測試代碼:
Map<Person2,Integer> map2 = new TreeMap<>(new Comparator<Person2>(){@Overridepublic int compare(Person2 o1, Person2 o2){if(o1 == null || o2 == null)return 0;return o1.getAge()-o2.getAge();}});Person2 p1 = new Person2("zzh",18);Person2 p2 = new Person2("jj",17);Person2 p3 = new Person2("qq",19);map2.put(p1, 1);map2.put(p2, 2);map2.put(p3, 3);for(Entry<Person2, Integer> entry:map2.entrySet()){System.out.println(entry.getKey()+":"+entry.getValue());}??輸出結(jié)果:
jj:17:2 zzh:18:1 qq:19:3??可以看到Person2中并沒有實(shí)現(xiàn)Comparable接口,但是想要和Person1一樣能夠和TreeMap合作,只需要在創(chuàng)建TreeMap的構(gòu)造函數(shù)中聲明一個(gè)Comparator接口的實(shí)現(xiàn),譬如上面的例子所示。
3. 由所有此類的“collection 視圖方法”所返回的迭代器都是快速失敗的。
??這點(diǎn)和HashMap一樣,所謂快速失敗就是在并發(fā)集合中,其進(jìn)行迭代操作時(shí),若有其他線程對其結(jié)構(gòu)性的修改,這是迭代器會(huì)立馬感知到,并且立刻拋出ConcurrentModificationException異常,而不是等待迭代完成之后才告訴你已經(jīng)出錯(cuò)。注意,迭代器的快速失敗行為無法得到保證,因?yàn)橐话銇碚f,不可能對是否出現(xiàn)不同步并發(fā)修改做出任何硬性保證。 快速失敗迭代器會(huì)盡最大努力拋出 ConcurrentModificationException。 因此,為提高這類迭代器的正確性而編寫一個(gè)依賴于此異常的程序是錯(cuò)誤的做法:迭代器的快速失敗行為應(yīng)該僅用于檢測 bug。
4. 和HashMap一樣,如果插入重復(fù)的元素,后面的元素會(huì)覆蓋前面的。
5. 鍵不可以為null(如果比較器對null做了處理,就可以為null),但是值可以為null。
??如上面的案例中,加入:
??在打印map2的時(shí)候就不會(huì)報(bào)錯(cuò)。
6. TreeMap對containsKey、get、put 和 remove 操作提供了保證的 log(n) 時(shí)間開銷。
??TreeMap提供了很多方法方便大小使用,譬如containsKey, get, put,remove,entrySet等Map通用的方法,也包括fisrtEntry, firstKey, cellingKey, lowerKey等方法,由于篇幅較大,不便贅述,使用前最好翻看一下API或者源碼熟悉一下。
HashMap與TreeMap的區(qū)別
HashMap:基于哈希表實(shí)現(xiàn)。使用HashMap要求添加的鍵類明確定義了hashCode()和equals()[可以重寫hashCode()和equals()],為了優(yōu)化HashMap空間的使用,您可以調(diào)優(yōu)初始容量和負(fù)載因子。
(1)HashMap(): 構(gòu)建一個(gè)空的哈希映像
(2)HashMap(Map m): 構(gòu)建一個(gè)哈希映像,并且添加映像m的所有映射
(3)HashMap(int initialCapacity): 構(gòu)建一個(gè)擁有特定容量的空的哈希映像
(4)HashMap(int initialCapacity, float loadFactor): 構(gòu)建一個(gè)擁有特定容量和加載因子的空的哈希映像
TreeMap:基于紅黑樹實(shí)現(xiàn)。TreeMap沒有調(diào)優(yōu)選項(xiàng),因?yàn)樵摌淇偺幱谄胶鉅顟B(tài)。
(1)TreeMap():構(gòu)建一個(gè)空的映像樹
(2)TreeMap(Map m): 構(gòu)建一個(gè)映像樹,并且添加映像m中所有元素
(3)TreeMap(Comparator c): 構(gòu)建一個(gè)映像樹,并且使用特定的比較器對關(guān)鍵字進(jìn)行排序
(4)TreeMap(SortedMap s): 構(gòu)建一個(gè)映像樹,添加映像樹s中所有映射,并且使用與有序映像s相同的比較器排序
HashMap:適用于在Map中插入、刪除和定位元素。
TreeMap:適用于按自然順序或自定義順序遍歷鍵(key)。
HashMap通常比TreeMap快一點(diǎn)(樹和哈希表的數(shù)據(jù)結(jié)構(gòu)使然),建議多使用HashMap,在需要排序的Map時(shí)候才用TreeMap.
參考資料
歡迎跳轉(zhuǎn)到本文的原文鏈接:https://honeypps.com/java/java-collection-treemap/
歡迎支持筆者新作:《深入理解Kafka:核心設(shè)計(jì)與實(shí)踐原理》和《RabbitMQ實(shí)戰(zhàn)指南》,同時(shí)歡迎關(guān)注筆者的微信公眾號:朱小廝的博客。
總結(jié)
以上是生活随笔為你收集整理的Java集合框架:TreeMap的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java集合框架:LinkedHashM
- 下一篇: Java集合框架:WeakHashMap