JDK 1.8 前,HashMap 採用「數組 + 鏈表」結構解決哈希沖突。極端情況下(大量鍵哈希碰撞),鏈表退化導致 get() 時間複雜度從 O(1) 降為 O(n)。為解決此性能隱患,JDK 1.8 引入紅黑樹替代長鏈表。
此動態切換將最壞情況查找複雜度從 O(n) 降為 O(log n)。
採用此優化的類:HashMap、LinkedHashMap、ConcurrentHashMap。
不採用的類: Hashtable、WeakHashMap、IdentityHashMap。Hashtable 為保持迭代順序兼容性拒絕樹化;WeakHashMap、IdentityHashMap 因特殊用途未引入。
hashCode() 計算索引。equals() 與 hashCode() 契約:相同對象 hashCode 必相同,但 hashCode 相同不代表對象相同。樹化後迭代順序會改變,但 HashMap 本身不保證迭代順序,故不影響正確性。Hashtable 為兼容舊代碼依賴順序特性,堅持不樹化。
JDK 1.8 通過紅黑樹優化極端哈希沖突性能,體現「鏈表存儲、頻繁沖突樹化」的動態適應策略。開發者應正確重寫 hashCode() 與 equals(),減少碰撞概率,發揮 HashMap 最佳性能。