Node[] table // transient,桶數組,長度永遠是 2 的冪次 │ ├─ Node (單向鏈表節點) // hash 衝突時鏈接 │ final int hash; K key; V value; Node next; │ └─ TreeNode (紅黑樹節點,繼承 Node) // 鏈表長度 ≥ 8 且 table ≥ 64 時樹化 TreeNode parent; left; right; prev; boolean red;
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // 16
static final int MAXIMUM_CAPACITY = 1 << 30; // 1073741824
static final float DEFAULT_LOAD_FACTOR = 0.75f;
static final int TREEIFY_THRESHOLD = 8; // 鏈表→樹
static final int UNTREEIFY_THRESHOLD = 6; // 樹→鏈表
static final int MIN_TREEIFY_CAPACITY = 64; // 最小樹化容量
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
高 16 位參與低位運算,減少哈希碰撞,提升低位熵值。
table == null → resize() 初始化i = (n-1) & hash 定位桶索引newNode 直接放入== 或 equals()) → 覆蓋舊值,返回 oldValuenewNode 掛尾部TREEIFY_THRESHOLD → treeifyBin() 樹化++size > threshold → resize() 擴容(e.hash & oldCap) == 0 → 留在原索引原索引 + oldCapgetTreeNode() 紅黑樹查找 O(log n)equals()public final class UserId {
private final long value;
public UserId(long value) { this.value = value; }
@Override public int hashCode() {
return Long.hashCode(value); // 或 (int)(value ^ (value >>> 32))
}
@Override public boolean equals(Object obj) {
return obj instanceof UserId other && this.value == other.value;
}
}
鐵律:equals() 相等 ⇒ hashCode() 必相等。違反將導致 get/put/remove 失效。
HashMap.newHashMap(int mappings) 靜態工廠,預計算容量避免多次擴容| 場景 | 建議 |
|---|---|
| 預知大約數據量 | new HashMap<>( (int)(N/0.75) + 1 ) 一次性分配 |
| 高併發讀寫 | 改用 ConcurrentHashMap(CAS + synchronized 細粒度鎖) |
| Key 為長字符串 | 預計算 hashCode 緩存,或用 String.intern() 減少對象 |
| 頻繁遍歷 | 考慮 LinkedHashMap 保持插入/訪問順序 |