TreeMap的源碼學習java
一)、TreeMap的特色算法
根據key值進行排序。數據結構
二)、按key值排序的兩種排序算法實現ide
1).在構造方法中傳入比較器性能
public TreeMap(Comparator<? super K> comparator) { this.comparator = comparator; } 比較器comparator實現Comparator接口,實現compare(T o1, T o2)方法; int compare(T o1, T o2);
2).key值實現Comparable接口,重寫 compareTo(key k)方法學習
T implements Comparable<T>{ @override public int compareTo(T k) }
注: 對於TreeMap而言,排序是一個必須進行的過程,要正常使用TreeMap必須制 定排序規則,加入Comparator或key對象實現Comparable接口,若沒有制定 比較規則則會拋出java.lang.ClassCastException。this
由於String對象默認實現了Comparable接口,實現了comparaTo方法,使用String類型做爲key值,不用進行排序。code
三)、TreeMap的數據結構orm
紅黑樹:Entry<k, v>對象
Entry<k ,v> 對象的屬性:
K key; V value; Entry<k, v> left; Entry<k, v> right; Entry<k, v> parent; boolean color = BLACK;
紅黑樹是一種平衡查找樹.
四)、TreeMap的主要屬性
//比較器 private final Comparator<? super K> comparator; //樹的根節點 private transient Entry<K,V> root; //節點個數即元素個數 private transient int size = 0; //修改次數 private transient int modCount = 0; //用於構造紅黑樹 private static final boolean RED = false; private static final boolean BLACK = true;
五)、TreeMap的put(K key, V value)方法
步驟:
1).獲取root節點,判斷是否第一次添加元素 ,如果第一次添加元素則將該元素設爲根節點。
2).如若不是第一次添加,根據key值,調用比較規則從根節點開始比較左右子樹直至到達葉子節點,根據key的比較結果決定放置到葉子節點的左樹位置或右樹位置,> 0放置右樹, < 0 放置右樹。
3).fixAfterInsertion修改插入元素後樹的結構,轉爲紅黑樹。
TreeMap<String, String> treeMap = new TreeMap<>(); treeMap.put("a","v"); public V put(K key, V value) { //獲取根節點 Entry<K,V> t = root; //若根節點爲空,直接將元素設爲樹的根節點,不用遍歷左右子樹 if (t == null) { compare(key, key); // type (and possibly null) check //將元素設爲樹的根節點 root = new Entry<>(key, value, null); size = 1; modCount++; return null; } //根據排序規則將元素插入到樹結構中 int cmp; Entry<K,V> parent; // split comparator and comparable paths Comparator<? super K> cpr = comparator; //判斷是否加入比較器,如加入了比較器,使用比較器的插入規則 if (cpr != null) { do { parent = t; //使用比較器的插入規則 cmp = cpr.compare(key, t.key); if (cmp < 0) t = t.left; else if (cmp > 0) t = t.right; else return t.setValue(value); } while (t != null); } //使用key 實現Comparable的compareTo()規則 else { if (key == null) throw new NullPointerException(); @SuppressWarnings("unchecked") /** 若是Key沒有加入比較器或沒有實現Comparable這裏就 拋出java.lang,ClassCastException */ Comparable<? super K> k = (Comparable<? super K>) key; //一直比較左右子樹的key值,直至到達葉子節點 do { parent = t; cmp = k.compareTo(t.key); if (cmp < 0) t = t.left; else if (cmp > 0) t = t.right; else return t.setValue(value); } while (t != null); } //根據返回的比較結果決定插入節點的位置 Entry<K,V> e = new Entry<>(key, value, parent); //< 0 做爲節點的左子樹 if (cmp < 0) parent.left = e; // > 0 做爲節點的右子樹 else parent.right = e; //調整插入元素的樹結構,轉爲紅黑樹 fixAfterInsertion(e); size++; modCount++; return null; }
六)、TreeMap的get(K key)方法
步驟:
1).獲取根節點
2).從根節點開始比較左右子樹的key值
3).若樹中某一節點的key值與查找的key值相等,則返回對應的Entry<k, v>對象
treeMap.get("a"); public V get(Object key) { Entry<K,V> p = getEntry(key); return (p==null ? null : p.value); } final Entry<K,V> getEntry(Object key) { // Offload comparator-based version for sake of performance //判斷是否存在比較器,如有比較器,則使用比較器的比較規則 if (comparator != null) return getEntryUsingComparator(key); if (key == null) throw new NullPointerException(); @SuppressWarnings("unchecked") //沒有比較器使用comparale的compareTo()規則 Comparable<? super K> k = (Comparable<? super K>) key; Entry<K,V> p = root; //從根節點遍歷左右子樹,若key值相等,則返回當前節點對象 while (p != null) { int cmp = k.compareTo(p.key); if (cmp < 0) p = p.left; else if (cmp > 0) p = p.right; else return p; } return null; }
注:TreeMap的功能比HashMap的功能強大, 實現了sortedMap接口,能夠對元素 進行排序,單TreeMap的性能卻略低於HashMap,當須要對集合進行排序操做可以使用TreeMap.