├── 1. 基础认知(必背开场)
│ ├── 实现接口:Map、Cloneable、Serializable
│ ├── 允许:1个 null key + 多个 null value
│ ├── 不允许:重复 key(覆盖旧值)
│ ├── 非线程安全
│ ├── 无序(不保证迭代顺序)
│ └── 默认参数
│ ├── 初始容量:16
│ ├── 负载因子:0.75f
│ └── 扩容阈值:capacity × loadFactor(默认12)
├── 2. 底层数据结构(最核心考点)
│ ├── 整体:数组 + 链表 + 红黑树(JDK 8 引入,至今不变)
│ ├── 数组:Node[] table(哈希桶 / bucket)
│ ├── 链表:Node 节点(冲突时链式存储)
│ └── 红黑树:TreeNode(链表长度 ≥8 且 容量 ≥64 时转换)
│ ├── TREEIFY_THRESHOLD = 8(转树阈值)
│ ├── UNTREEIFY_THRESHOLD = 6(退化阈值)
│ └── MIN_TREEIFY_CAPACITY = 64(最小树化容量)
├── 3. Hash 计算与定位(常追问细节)
│ ├── hash() 方法:key.hashCode() 高16位 ^ 低16位(扰动函数)
│ ├── 索引计算:(n-1) & hash (n=容量,必须2的幂)
│ └── 为什么 2 的幂?位运算更快,等价 hash % n
├── 4. 冲突解决与树化(高频深度题)
│ ├── 冲突 → 链表(JDK 7/8 头插 vs 尾插)
│ ├── 链表长度 ≥8 + 容量 ≥64 → treeifyBin() → 红黑树
│ ├── 为什么 8?泊松分布下概率极低 → hash 很可能失效
│ ├── 为什么不直接转树?小容量转树浪费内存,先扩容
│ └── 退化:remove / resize 时 ≤6 → untreeify → 链表
├── 5. 扩容机制(resize,高频必问)
│ ├── 触发:size > threshold(容量 × 负载因子)
│ ├── 新容量 = 旧容量 × 2
│ ├── rehash:所有节点重新计算索引(JDK 8+ 优化,不全量重算)
│ ├── JDK 7:头插法 → 多线程死循环
│ └── JDK 8+:尾插法 → 无死循环,但仍可能数据覆盖
├── 6. 线程不安全 & 解决方案(并发必考)
│ ├── JDK 7 表现:死循环(环形链表)
│ ├── JDK 8+ 表现:数据丢失 / 覆盖
│ └── 线程安全替代方案(按推荐顺序背)
│ ├── ConcurrentHashMap(首选,CAS + synchronized 细粒度锁)
│ ├── Collections.synchronizedMap(new HashMap<>())(全局锁,效率低)
│ ├── Hashtable(过时,全方法 synchronized)
│ └── 业务加锁(ReentrantLock / synchronized)
├── 7. 性能与复杂度
│ ├── 平均:O(1) get / put / remove
│ ├── 最坏:O(log n)(树化后)
│ ├── 极端无树化:O(n)
│ └── 迭代时间 ≈ capacity + size(容量浪费影响迭代)
├── 8. 关键方法 & 使用技巧(函数式编程常考)
│ ├── put / get / remove / containsKey
│ ├── getOrDefault
│ ├── putIfAbsent
│ ├── computeIfAbsent(懒初始化神器)
│ ├── merge(累加 / word count 经典)
│ └── forEach / entrySet / keySet / values
├── 9. JDK 版本对比(高级追问)
│ ├── JDK 7 及以前:数组 + 链表 + 头插法 + 死循环风险
│ └── JDK 8+(至今):尾插法 + 红黑树 + 扰动函数 + 无死循环
└── 10. 常见追问一句话总结(快速应对)
├── 为什么容量 2 的幂? → 位运算代替取模
├── 负载因子为什么 0.75? → 时间与空间折中
├── 为什么用红黑树而不是 AVL? → 插入/删除更快,红黑树更平衡代价小
├── 自定义对象做 key 必须做什么? → 重写 equals + hashCode,且保持一致
└── 项目中怎么优化 HashMap? → 预估容量避免多次扩容、选择合适初始容量、避免 hash 冲突严重的 key
参考文档:
https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/HashMap.html
https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/util/HashMap.java