Java Map 家族核心解析
------ HashMap → LinkedHashMap → TreeMap 的设计取舍与工程应用
0. 为什么要把这三者放在一起讲?
Map 的核心问题只有三个:
快不快?顺不顺?能不能比较大小?
| Map | 解决的核心问题 |
|---|---|
| HashMap | 快 |
| LinkedHashMap | 快 + 有顺序 |
| TreeMap | 有序(按大小) |
👉 这是同一条设计演进链,不是三个孤立容器
1. HashMap:只关心"能不能最快找到"
1.1 设计目标
- O(1) 平均查找
- 不关心遍历顺序
- 空间换时间
1.2 底层结构(JDK 8+)
text
数组 + 链表 / 红黑树
- hash → index
- 冲突 → 链表
- 链表 ≥ 8 → 红黑树
📌 工程关键词:hash 扰动、负载因子、扩容、树化
1.3 HashMap 的"无序"到底是什么意思?
- 遍历顺序 ≠ 插入顺序
- 扩容后顺序可能变化
- 顺序依赖 hash 分布
⚠️ 无序 ≠ 随机
1.4 HashMap 的适用场景
✅ 只关心查找
✅ 不关心顺序
✅ 数据量大、性能敏感
【面试高亮框】
- 为什么 HashMap 查询快?
- 为什么容量是 2 的幂?
- 为什么 table 只会变大不会变小?
2. LinkedHashMap:在 HashMap 上"补一条链表"
2.1 LinkedHashMap 的定位
HashMap + 顺序语义
不是新结构,而是增强版 HashMap
2.2 底层结构
text
HashMap
+ 双向链表
java
Entry<K,V> {
K key;
V value;
Entry before;
Entry after;
}
📌 HashMap 负责定位,链表负责顺序
2.3 两种顺序模式(非常重要)
1️⃣ 插入顺序(默认)
java
new LinkedHashMap<>();
- put 顺序 = 遍历顺序
- 扩容不影响顺序
2️⃣ 访问顺序(LRU 模式)
java
new LinkedHashMap<>(16, 0.75f, true);
- get / put 会把节点移到尾部
- 头结点 = 最久未使用
2.4 为什么 LinkedHashMap 还能保持 O(1)?
- 查找:HashMap(O(1))
- 调整顺序:双向链表(O(1))
👉 没有排序、没有遍历
2.5 经典工程应用:LRU Cache
java
class LRUCache<K,V> extends LinkedHashMap<K,V> {
protected boolean removeEldestEntry(...) {
return size() > capacity;
}
}
📌 这是 LinkedHashMap 存在的最大工程意义
【面试高亮框】
- LinkedHashMap 和 HashMap 的区别?
- accessOrder=true 有什么用?
- 为什么 LinkedHashMap 能实现 LRU?
3. TreeMap:彻底换一套思路,用"比较"而不是"hash"
3.1 TreeMap 的核心思想
不用 hash,用 key 的大小关系
3.2 底层结构
text
红黑树(Red-Black Tree)
- 自平衡
- 查找 / 插入 / 删除:O(log n)
3.3 TreeMap 的排序规则
1️⃣ key 实现 Comparable
java
class User implements Comparable<User>
2️⃣ 构造时传 Comparator
java
new TreeMap<>((a, b) -> b - a);
⚠️ 排序规则决定 key 唯一性
3.4 为什么 TreeMap 不允许 null key?
TreeMap 在任何操作中都必须比较 key,而 null 无法参与比较。
3.5 TreeMap 的"独家能力":范围查询 ⭐
java
subMap()
headMap()
tailMap()
floorKey()
ceilingKey()
👉 HashMap / LinkedHashMap 完全不支持
3.6 TreeMap 的典型应用
- 时间轴
- 排行榜
- 区间统计
- 最近值查找
【面试高亮框】
- TreeMap 判重看什么?
- compareTo 返回 0 会发生什么?
- TreeMap 和 TreeSet 的关系?
4. 三者终极对比(工程选型)
| 特性 | HashMap | LinkedHashMap | TreeMap |
|---|---|---|---|
| 查找速度 | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐ |
| 是否有序 | ❌ | ✅ | ✅ |
| 顺序依据 | hash | 插入 / 访问 | key 大小 |
| 范围查询 | ❌ | ❌ | ✅ |
| 内存占用 | 低 | 中 | 高 |
| 典型用途 | KV 存储 | LRU / 有序输出 | 排序 / 区间 |
5. 如何在工程中选型?(一句话版本)
- 要快,不要顺序 → HashMap
- 要顺序,不要排序 → LinkedHashMap
- 要排序 / 范围 → TreeMap
6. 结语:这是三种"取舍",不是三种"层级"
HashMap 追求极致性能
LinkedHashMap 追求工程可控性
TreeMap 追求语义表达能力
📌 附录:Map 家族常见误区
- LinkedHashMap ≠ 排序
- TreeMap ≠ 快
- HashMap ≠ 随机