TreeMap 實現了 SortedMap 和 NavigableMap 接口,所有本文還會記錄 SortedMap 和 NavigableMap 的閱讀筆記。
SortedMap
1. 排序的比較應該和 equals(Object) 保持一致
2. 應該提供四種“標准”的構造器
1). 無參構造器
2). 帶一個 Comparator 為參數的構造器
3). 帶一個 Map 為參數的構造器
4). 帶一個 SortedMap 為參數的構造器
3. subMap , headMap , tailMap , KeySet , values, entrySet 等方法返回的 Map 或 Set 和 SortedMap 本身使用同一份數據,所以對 subMap 返回的 Map 進行修改,同樣會反映到 SortedMap 上。
NavigableMap
1. lowerEntry, floorEntry, ceilingEntry, higherEntry 分別返回 小於、小於或等於,大於或等於,以及大於給定 key 的 Map.Entry。這類型的方法用於定位離目標給定值最近的元素。
2. 增長序 map 的操作比遞減序的 map 的操作要快。
3. 返回 entry 的方法返回的是那一刻的 entry 快照,所以通常不支持 Entry.setValue 方法。
例如, TreeMap 實現 NavigableMap 的 firstEntry,返回會的就是根據給定 entry 的 key, value 新建的不可變
SimpleImmutableEntry 對象。
4. pollFirstEntry 刪除並返回第一個元素
TreeMap
1. 基於紅黑樹的實現
2. 根據自然序,或者給定的比較器是內部元素保持有序。
3. 提供復雜度為 log(n) 的 containsKey, get, put, remove 操作
4. itertator 采用 fast-fail 機制
5. values 繼承於 Collection, EntrySet 和 KeySet 則繼承於 Set
6. DeletionEntry 刪除指定的元素,fixAfterDeletion 對刪除后的樹節點進行再平衡,使得 TreeMap 保持紅黑樹的特性。
7. containsValue(Object) 通過遍歷所有元素,來判斷是否包含指定的值為 value。因此,效率低。
public boolean containsValue(Object value) { for (Entry<K,V> e = getFirstEntry(); e != null; e = successor(e)) if (valEquals(value, e.value)) return true; return false; }
8. getFirstEntry 返回樹中最左下角的元素
final Entry<K,V> getFirstEntry() { Entry<K,V> p = root; if (p != null) while (p.left != null) p = p.left; return p; }
getLastEntry 返回樹中最右下角的元素
final Entry<K,V> getLastEntry() { Entry<K,V> p = root; if (p != null) while (p.right != null) p = p.right; return p; }
9. successor(Entry e)
當 e 為 null 時,返回 null
當 e 有右子節點時,則返回右子節點的最左下角后代節點
當 e 沒有右子節點時,返回一個離 e 最近的祖先節點,該祖先節的左孩子也是 e 的祖先節點。
static <K,V> TreeMap.Entry<K,V> successor(Entry<K,V> t) { if (t == null) return null; else if (t.right != null) { Entry<K,V> p = t.right; while (p.left != null) p = p.left; return p; } else { Entry<K,V> p = t.parent; Entry<K,V> ch = t; while (p != null && ch == p.right) { ch = p; p = p.parent; } return p; } }
10. prodecessor(Entry e) 和 successor(Entry e) 思路相似。
當 e 為 null 時,返回 null
當 e 有左子節點時,則返回左子節點的最右下角后代節點
當 e 沒有左子節點時,返回一個離 e 最近的祖先節點,該祖先節的右孩子也是 e 的祖先節點。
static <K,V> Entry<K,V> predecessor(Entry<K,V> t) { if (t == null) return null; else if (t.left != null) { Entry<K,V> p = t.left; while (p.right != null) p = p.right; return p; } else { Entry<K,V> p = t.parent; Entry<K,V> ch = t; while (p != null && ch == p.left) { ch = p; p = p.parent; } return p; } }
11. get(Object):V 和 getEntry(Object):Entry 的不同點在於,前者返回 V, 而后者返回 Entry。獲取的算法一樣,因為 get 是基於 getEntry 來實現的。
public V get(Object key) { Entry<K,V> p = getEntry(key); return (p==null ? null : p.value); }
12. containsKey(Object) 同樣也是基於 getEntry 來實現的
public boolean containsKey(Object key) { return getEntry(key) != null; }
13. computeRedLevel(int) ,應用於復制一個 map 到當前為空的 TreeMap 的操作中。復制后的 TreeMap 應該是一棵完全二叉樹(complete binary tree),通過將其中滿足完美二叉樹(perfect binary tree)部分的節點塗黑,則可以簡單地實現紅黑樹的黑屬性。
private static int computeRedLevel(int sz) { int level = 0; for (int m = sz - 1; m >= 0; m = m / 2 - 1) level++; return level; }
下面是一個完全二叉樹的例子,其中滿足完美二叉樹的只有 0 - 7 個節點,也就是 0 - 2 層。0 - 2 層的節點全部塗黑色,最后一層則全部塗紅色。則最方便地滿足紅黑樹的特性。
14. buildFromSorted, 采用遞歸的思路,先構建后節點的左子樹,在構建好節點的右子樹,最后和節點組合成一個完整的子樹。
15. putAll(Map),
當 TreeMap 沒有元素,Map 是一個 sortMap, 並且 Map 的比較器等於 TreeMap 的比較器,則采用 buildFormSorted 來構建 TreeMap。
否則,將 Map 中每個 mapping,通過調用 put(K, V) 來插入 TreeMap 中。
public void putAll(Map<? extends K, ? extends V> map) { int mapSize = map.size(); if (size==0 && mapSize!=0 && map instanceof SortedMap) { Comparator<?> c = ((SortedMap<?,?>)map).comparator(); if (c == comparator || (c != null && c.equals(comparator))) { ++modCount; try { buildFromSorted(mapSize, map.entrySet().iterator(), null, null); } catch (java.io.IOException cannotHappen) { } catch (ClassNotFoundException cannotHappen) { } return; } } super.putAll(map); }
16. getEntry, getEntryUsingComparator, getCeilingEntry, getFloorEntry, getHigherEntry, getLowerEntry 都是基於二分查找思路來實現元素操作。
17. put(K, V)
當已存在 key 和 K 相等的 Entry, 則直接更新這個 Entry 的 value 值。
否則,插入新的 Entry ,然后自平衡樹結構。
18. remove(Object),刪除指定節點,然后自平衡樹結構
19. clear(), 將 root 至 null 即可
public void clear() { modCount++; size = 0; root = null; }
20. firstEntry 返回不可變的 Entry , getFirstEntry 則返回可變的 Entry。同樣關系的還有:lastEntry 和 getLastEntry,lowerEntry 和 getLowerEntry, higherEntry 和 getHigherEntry。
Jdk 版本: jdk1.8.0_31.jdk