Java Map 家族核心解析

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 ≠ 随机
相关推荐
浅念-2 小时前
C语言小知识——指针(3)
c语言·开发语言·c++·经验分享·笔记·学习·算法
一嘴一个橘子2 小时前
springMvc 接收参数、cookie、header
java
code_li3 小时前
聊聊支付宝架构
java·开发语言·架构
少控科技4 小时前
QT高阶日记01
开发语言·qt
CC.GG4 小时前
【Linux】进程概念(五)(虚拟地址空间----建立宏观认知)
java·linux·运维
无限进步_4 小时前
【C++】大数相加算法详解:从字符串加法到内存布局的思考
开发语言·c++·windows·git·算法·github·visual studio
“抚琴”的人4 小时前
C#上位机工厂模式
开发语言·c#
巨大八爪鱼4 小时前
C语言纯软件计算任意多项式CRC7、CRC8、CRC16和CRC32的代码
c语言·开发语言·stm32·crc
C+-C资深大佬4 小时前
C++ 数据类型转换是如何实现的?
开发语言·c++·算法