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
