Skip to content
极高进阶

一句话答案

JDK8 的 HashMap 是数组+链表+红黑树,默认容量 16 负载因子 0.75,链表长度 ≥8 且数组 ≥64 时转红黑树。

核心要点

JDK 8 的 HashMap 结构:数组 + 链表 + 红黑树

数组(Node[] table)
 index 0: null
 index 1: Node(key1, val1) → Node(key2, val2) → null  ← 链表(哈希冲突)
 index 2: TreeNode(...)                                 ← 红黑树(链表长度≥8后转换)
 index 3: null
 ...
 index n: Node(keyN, valN)

核心字段:

java
transient Node<K,V>[] table;    // 哈希桶数组
transient int size;             // 实际键值对数量
int threshold;                  // 扩容阈值 = capacity * loadFactor
final float loadFactor;         // 负载因子,默认 0.75
transient int modCount;         // 修改计数,fail-fast 用

哈希计算(扰动函数):

java
static final int hash(Object key) {
    int h;
    // 高16位与低16位异或,目的:让高位参与散列,减少冲突
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

// 确定数组下标:(capacity - 1) & hash
// 等价于 hash % capacity(因为 capacity 是2的幂)

为什么 capacity 必须是 2 的幂? 使得 hash % capacity 可以用位运算 (capacity-1) & hash 代替,效率更高,且 capacity-1 全为 1,使 hash 低位都能参与索引计算,分布更均匀。

追问与易错

追问方向:

  • 为什么链表转红黑树的阈值是 8?(泊松分布,链表长度达到 8 的概率极低)
  • HashMap 是线程安全的吗?并发下会出什么问题?(数据覆盖/死循环 JDK7)
  • 为什么容量必须是 2 的幂次?(hash & (n-1) 等价于取模但更快)

易错点:

  • ❌ "红黑树在链表长度到 8 就转换"——还需数组长度 ≥ 64,否则优先扩容
  • ❌ 混淆 hashCode 和 equals 的关系——equals 相��则 hashCode 必须相等,反之不一定

💡 记忆锚点

16层公寓按门牌取模入住,冲突排队(链表),队伍超8人且楼层超64层时换红黑树调度,住满75%整栋翻倍扩建。hash先高低16位异或"搅匀"再定位。