TreeMap 是 Java 集合框架中基於紅黑樹實現的有序 Map,保證鍵有序、單次操作 O(log n)。本文從比較器策略、節點結構、插入/刪除/查找核心邏輯、紅黑樹修復旋轉、遍歷迭代器五大維度,配合源碼片段與 ASCII 圖解,徹底講透 TreeMap 內部機制。
// 構造函數決定比較策略
public TreeMap() { comparator = null; } // 自然序:鍵需實現 Comparable
public TreeMap(Comparator super K> comparator) { this.comparator = comparator; } // 定製序
// put 時的比較邏輯
Comparator super K> cpr = comparator;
if (cpr != null) {
cmp = cpr.compare(key, t.key); // 定製比較器
} else {
@SuppressWarnings("unchecked")
Comparable super K> k = (Comparable super K>) key;
cmp = k.compareTo(t.key); // 自然序
}
Comparable,通用性強Comparator 策略模式static final class Entryimplements 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; } }
put(key, value) ↓ 根為空? → 創建根節點 (黑) → 返回 ↓ BST 查找定位父節點 parent ↓ 鍵已存在? → 更新值 → 返回舊值 ↓ 創建新節點 e (紅),掛在 parent 左/右 ↓ fixAfterInsertion(e) → 紅黑修復核心 ↓ size++ → 返回 null
while (e != root && e.parent.color == RED) {
if (e.parent == e.parent.parent.left) { // 父是左孩子
Entry y = e.parent.parent.right; // 叔父
if (y != null && y.color == RED) { // 情況1:叔父紅 → 變色
e.parent.color = BLACK;
y.color = BLACK;
e.parent.parent.color = RED;
e = e.parent.parent; // 向上繼續檢查
} else { // 叔父黑/無
if (e == e.parent.right) { // 情況2:內側插入 → 左旋轉父
e = e.parent;
rotateLeft(e);
}
// 情況3:外側插入 → 變色 + 右旋轉祖父
e.parent.color = BLACK;
e.parent.parent.color = RED;
rotateRight(e.parent.parent);
}
} else { // 父是右孩子,鏡像邏輯
// ... 左右互換
}
}
root.color = BLACK; // 根永遠黑
while (x != root && colorOf(x) == BLACK) {
if (x == x.parent.left) { // x 是左孩子
Entry w = x.parent.right; // 兄弟
if (colorOf(w) == RED) { // 情況1:兄弟紅 → 變色 + 左旋父
w.color = BLACK;
x.parent.color = RED;
rotateLeft(x.parent);
w = x.parent.right;
}
if (colorOf(w.left) == BLACK && colorOf(w.right) == BLACK) { // 情況2:兄弟雙黑子 → 兄弟變紅 + 向上
w.color = RED;
x = x.parent;
} else {
if (colorOf(w.right) == BLACK) { // 情況3:兄弟左紅右黑 → 兄弟右旋 + 變色
w.left.color = BLACK;
w.color = RED;
rotateRight(w);
w = x.parent.right;
}
// 情況4:兄弟右紅 → 父色給兄弟 + 父變黑 + 右侄變黑 + 左旋父
w.color = colorOf(x.parent);
x.parent.color = BLACK;
w.right.color = BLACK;
rotateLeft(x.parent);
x = root; // 結束循環
}
} else { // 鏡像邏輯
// ...
}
}
if (x != null) x.color = BLACK;
場景 建議 頻繁範圍查詢 TreeMap 優於 HashMap + 排序 高併發寫入 ConcurrentSkipListMap (跳表,無鎖/細粒度鎖) 鍵為自定義對象 必須實現 Comparable 或傳 Comparator,保證一致性 (equals 與 compareTo 一致) 大量鍵重複插入 put 返回舊值,避免創建新 Entry 對象 序列化/反序列化 紅黑樹結構序列化開銷大,考慮 JSON 扁平化存儲 「TreeMap 將紅黑樹這一經典數據結構工程化為通用集合,其源碼中『雙向導航 + 顏色標記 + 旋轉修復』的模式,是學習平衡樹實現的最佳教材。掌握其修復邏輯,面試手寫紅黑樹插入/刪除不再是夢魘。」