TreeMap 基於紅黑樹實現,保證鍵有序、單操作 O(log n) 復雜度。本文剖析節點結構、構造器策略、插入刪除調整、與 HashMap 核心差異。
→ 任意路徑長度 ≤ 2 × 最短路徑,近似平衡。
static final class Entry implements Map.Entry {
K key; V value;
Entry left, right, parent;
boolean color = BLACK; // 新節點默認紅,構造器中設置
Entry(K key, V value, Entry parent) {
this.key = key; this.value = value; this.parent = parent;
}
// getKey/setValue/getValue 等 Map.Entry 方法
}
| 構造器 | 比較器 | Key 要求 | 適用場景 |
|---|---|---|---|
TreeMap() | null | 實現 Comparable | 自然順序 |
TreeMap(Comparator) | 指定 | 無需 Comparable | 自定義順序 |
TreeMap(Map) | null | 實現 Comparable | 複製任意 Map |
TreeMap(SortedMap) | 源 Map 的 | 同源 Map | 複製有序 Map,O(n) 批量構建 |
// SortedMap 構造器調用
buildFromSorted(size, iterator, null, null);
// 利用已有序序列,線性時間構建平衡紅黑樹
// 避免逐個插入的 O(n log n) 開銷
fixAfterInsertion(entry) 恢復紅黑性質
// 旋轉 + 重著色核心邏輯
private void fixAfterInsertion(Entry x) {
x.color = RED;
while (x != null && x != root && x.parent.color == RED) {
if (parentOf(x) == leftOf(grandParentOf(x))) {
Entry y = rightOf(grandParentOf(x)); // 叔節點
if (colorOf(y) == RED) { // Case 1: 叔紅 → 父/叔染黑、祖父染紅、向上繼續
setColor(parentOf(x), BLACK);
setColor(y, BLACK);
setColor(grandParentOf(x), RED);
x = grandParentOf(x);
} else {
if (x == rightOf(parentOf(x))) { // Case 2: 內側插入 → 先左旋轉父
x = parentOf(x);
rotateLeft(x);
}
// Case 3: 外側插入 → 父染黑、祖父染紅、右旋轉祖父
setColor(parentOf(x), BLACK);
setColor(grandParentOf(x), RED);
rotateRight(grandParentOf(x));
}
} else { // 鏡像情況:父是右孩子
// 對稱邏輯...
}
}
root.color = BLACK;
}
fixAfterDeletion(replacement) 恢復黑高平衡刪除調整最複雜,涉及 4 大情況、兄弟節點顏色、侄節點顏色組合,核心思想:向下傳遞黑色額外權重,通過旋轉/重著色消化。
| 維度 | TreeMap | HashMap |
|---|---|---|
| 底層結構 | 紅黑樹 | 數組 + 鏈表/紅黑樹 (JDK8) |
| 順序性 | Key 自然/自定義順序 | 無序 (LinkedHashMap 維護插入序) |
| Key 要求 | Comparable 或 Comparator | hashCode() + equals() |
| Null Key | ❌ 拋 NPE | ✅ 僅允許 1 個 |
| 查找/插入/刪除 | O(log n) 穩定 | O(1) 平均,最差 O(n)/O(log n) |
| 適用場景 | 範圍查詢、有序遍歷、頂部/底部元素 | 高頻點查詢、緩存、去重 |
TreeSet 內部持有 NavigableMap (實為 TreeMap),所有操作委託給 Map,PRESENT = new Object() 作為統一 Value。
TreeMap(SortedMap) 或先排序數組再 buildFromSortedsubMap/headMap/tailMap 視圖,無需複製ConcurrentSkipListMap