HashMap 面试全攻略

HashMap 面试全攻略(Java)

面试问 HashMap,本质就是在问:你到底懂不懂数据结构 + 并发 + JDK 演进

这份文档就是冲着"高级 / 资深 Java 面试"来的。


1. HashMap 是什么?

  • 基于 数组 + 链表 + 红黑树 的 Key-Value 数据结构
  • 非线程安全
  • 允许 null keynull value
  • JDK 1.8 之后:链表长度 ≥ 8 且数组长度 ≥ 64 → 链表转红黑树

2. HashMap 的核心数据结构

text 复制代码
Node<K,V>[] table

JDK 1.7

复制代码
数组 + 链表(头插法)

JDK 1.8

复制代码
数组 + 链表 + 红黑树(尾插法)

3. put() 底层流程(高频)

  1. 判断 table 是否为空 → resize
  2. 计算 hash
  3. (n - 1) & hash 定位桶位
  4. 桶为空 → 直接插入
  5. 桶不为空:
    • key 相同 → 覆盖
    • 链表 → 尾插
    • 判断是否树化
  6. 判断是否需要扩容

👉 面试金句

HashMap 的性能核心在于 hash 的均匀性 + 扩容成本控制


4. hash 为什么要高 16 位异或?

java 复制代码
hash = h ^ (h >>> 16)

原因

  • HashMap 的数组长度较小
  • 直接取低位容易冲突
  • 高低位混合,减少 hash 冲突

5. resize 扩容机制(必问)

  • 默认容量:16
  • 扩容因子:0.75
  • 扩容后容量:2 倍

JDK 1.8 的优化点

  • 不再重新 hash
  • 利用 (hash & oldCap) 判断新位置
text 复制代码
0 → 原位置
1 → 原位置 + oldCap

👉 扩容时间复杂度:O(n)


6. 为什么负载因子是 0.75?

权衡三点:

  • 空间利用率
  • 冲突概率
  • resize 成本

0.75 是 经验最优解,不是拍脑袋


7. 链表转红黑树的条件

同时满足:

  • 链表长度 ≥ 8
  • table.length ≥ 64

否则:优先扩容而不是树化

👉 这是为了避免小数组下树化带来的额外性能损耗


8. 为什么 JDK 1.7 用头插法,1.8 改成尾插?

JDK 1.7 问题

  • 扩容时可能 链表成环
  • 多线程 put → 死循环 100% CPU

JDK 1.8 改进

  • 尾插法
  • 扩容时顺序不变
  • 解决死循环问题(但依然不线程安全)

9. HashMap 为什么线程不安全?

典型问题

  1. 数据覆盖
  2. resize 并发导致数据丢失
  3. size 不准
  4. JDK 1.7 死循环

👉 面试官想听的是:结构性原因,不是"没加锁"


10. HashMap vs ConcurrentHashMap

对比点 HashMap ConcurrentHashMap
线程安全
锁粒度 CAS + synchronized
性能 略低
null key 支持 不支持

11. equals & hashCode 的关系(送分题)

规则:

  • equals 相等 → hashCode 必须相等
  • hashCode 相等 → equals 不一定相等

👉 写自定义 key 必须 重写 hashCode + equals


12. 常见面试连环追问

Q1:HashMap 查找复杂度?

  • 理想:O(1)
  • 最坏(链表):O(n)
  • 红黑树:O(log n)

Q2:为什么容量必须是 2 的幂?

  • (n - 1) & hash 等价于 % n
  • 位运算更快
  • 分布更均匀

Q3:Hash 冲突怎么解决?

  • 拉链法
  • 树化

13. 高频面试总结(直接背)

  • HashMap 本质是 空间换时间
  • JDK 1.8 的核心升级是:
    • 红黑树
    • 尾插法
    • 高效 resize
  • 面试重点永远在:
    • put / get
    • resize
    • 并发问题

14. 一句话总结(终极)

HashMap 的精髓不是 API,而是 在冲突、扩容、并发之间做工程权衡


相关推荐
小bo波11 小时前
使用Thread子类创建线程 VS 使用Runnable接口创建线程的区别
java·多线程·thread·并发编程·runnable
SamDeepThinking11 小时前
高并发场景下,CompletableFuture与ForkJoinPool该如何取舍?
java·后端·面试
张不才14 小时前
CPU 100% 了怎么办?Java 性能排障的标准化操作
java·后端
shepherd11116 小时前
吞吐量提升 10 倍:高并发大批量数据处理任务的架构演进与性能调优
java·后端·架构
plainGeekDev18 小时前
单例模式 → object 声明
android·java·kotlin
用户2986985301419 小时前
Java 实现 Word 文档文本与图片提取的方法
java·后端
SimonKing20 小时前
铁子,IntelliJ IDEA 2026.1.3来了,升不升?
java·后端·程序员
咖啡八杯1 天前
GoF设计模式——策略模式
java·后端·spring·设计模式
用户128526116022 天前
我把祖传Java项目重构后,接口响应从3s砍到了200ms,只改了这几行代码
java