1. 底層數據結構
- 數組+鏈表+紅黑樹(JDK 1.8+):
- 數組(
Node[] table
)存儲桶(bucket),每個桶是鏈表或紅黑樹的頭節點。 - 鏈表解決哈希沖突,當鏈表長度 ≥ 8 且數組容量 ≥ 64 時轉為紅黑樹(查找復雜度從O(n)優化到O(log n))。
- 數組(
2. 核心方法原理
-
put()
流程:- 計算鍵的哈希值(
hash(key)
),通過擾動函數(高16位異或低16位)減少沖突。 - 定位桶位置:
index = (n - 1) & hash
。 - 若桶為空直接插入;若沖突則遍歷鏈表/紅黑樹:
- 相同key:覆蓋舊值;
- 不同key:尾插法(JDK 1.8)或樹化(鏈表長度 ≥ 8)。
- 擴容條件:元素數 > 容量 × 負載因子(默認0.75)。
- 計算鍵的哈希值(
-
get()
流程:通過哈希值定位桶,遍歷鏈表/紅黑樹,用equals()
匹配key。
3. 擴容機制
- 容量翻倍:新建2倍數組,重新哈希遷移數據(JDK 1.8優化:僅需判斷高位哈希位,減少重新計算)。
- 線程不安全問題:多線程擴容可能導致死循環(JDK 1.7頭插法)或數據丟失。
4. 線程安全與替代方案
- 非線程安全:多線程操作需使用
ConcurrentHashMap
(分段鎖/CAS)或Collections.synchronizedMap
。
5. 關鍵參數與優化
- 初始容量:默認16,建議預估設置以減少擴容開銷。
- 哈希沖突優化:重寫
hashCode()
和equals()
確保鍵對象分布均勻。
6. 與其他Map對比
特性 | HashMap | LinkedHashMap | TreeMap |
---|---|---|---|
順序性 | 無序 | 插入/訪問順序 | 鍵的自然/自定義排序 |
線程安全 | 否 | 否 | 否 |
適用場景 | 高頻增刪查 | 需保留插入順序 | 需排序或范圍查詢 |
總結:HashMap通過哈希表實現高效查詢(平均O(1)),但需注意哈希沖突、擴容成本及線程安全問題。JDK 1.8引入紅黑樹優化極端情況性能,適用于單線程高頻操作場景。