主题
Java 集合框架技术栈总览
蒸馏自
github-hxq-note/Java/Java util/(6 篇)+语雀-Java开发/JavaSE/集合(2 篇),主题高度集中(List + Map + 并发 Map)。本页是集合域全局地图。
一句话机制
Java 集合分两大体系:Collection(List/Set/Queue,存单个元素)和 Map(存键值对);核心实现围绕「数组 + 链表 + 红黑树」三种底层结构取舍,线程安全靠「互斥(HashTable/Collections.synchronizedXxx)→ 分段锁(CHM1.7)→ CAS + 局部 synchronized(CHM1.8)」逐代演进。
集合体系全景
Collection Map
├── List(有序可重复) ├── HashMap(数组+链表+红黑树)
│ ├── ArrayList(动态数组) ├── LinkedHashMap(+双向链表保序)
│ └── LinkedList(双向链表) └── TreeMap(红黑树,有序)
├── Set(无序不可重复)
│ ├── HashSet(基于 HashMap)
│ └── TreeSet(基于 TreeMap)
└── Queue(队列)三大底层结构的取舍
| 结构 | 随机访问 | 增删 | 代表 |
|---|---|---|---|
| 动态数组 | O(1) 快 | O(n) 慢(要搬元素) | ArrayList |
| 双向链表 | O(n) 慢 | O(1) 快(改指针) | LinkedList |
| 哈希表(数组+链表+红黑树) | O(1)~O(logn) | O(1)~O(logn) | HashMap |
不变量:HashMap 用「数组 + 链表 + 红黑树」解决哈希冲突——冲突少用链表,冲突严重(链表 ≥8 且数组 ≥64)转红黑树,把查询从 O(n) 降到 O(logn)。
线程安全的演进(核心脉络)
| 方案 | 机制 | 问题 |
|---|---|---|
| HashTable | 全表 synchronized | 并发性能极差 |
| Collections.synchronizedMap | 包装 + 全表锁 | 同样全表锁 |
| ConcurrentHashMap 1.7 | Segment 分段锁(默认 16 段) | 分段间可并发,但锁粒度仍粗 |
| ConcurrentHashMap 1.8 | CAS + 局部 synchronized(锁单个 Node) | 锁粒度最细 + 红黑树 + 多线程扩容 |
演进主线一句话:锁粒度从「全表 → 段 → 单个桶(Node)」逐代变细,并发度逐代提升。CHM1.8 的锁粒度是 Node,配合 CAS 无锁读。
关键机制速览
- HashMap 哈希函数:
(h = key.hashCode()) ^ (h >>> 16)(高 16 位参与运算,减少低位冲突),索引hash & (length - 1) - HashMap 扩容:数组长度保持 2 的 n 次方;1.8 扩容后元素位置「要么不变、要么 +旧容量」
- ArrayList 扩容:无参构造首次 add 扩到 10,之后每次 1.5 倍(
oldCapacity + (oldCapacity >> 1)) - CHM1.8 计数:counterCells 分散热点(同 LongAdder),避免并发竞争单个 size
常见误解(避坑)
- ❌ "HashMap 是线程安全的"。→ 1.7 扩容死循环、1.8 并发 put 数据覆盖;并发场景用 CHM 或加锁。
- ❌ "链表元素一超过 8 就转红黑树"。→ 还有第二个条件:数组长度 ≥64,否则优先扩容而非树化。
- ❌ "ArrayList 一开始就有 10 容量"。→ 无参构造初始是空数组(容量 0),第一次 add 才扩到 10。
- ❌ "ConcurrentHashMap 读也要加锁"。→ 1.8 的 get 是无锁的(volatile + Unsafe 保证可见性)。
关联
- 原始资料:HashMap · ArrayList · LinkedList · LinkedHashMap · ConcurrentHashMap1.7 · ConcurrentHashMap1.8 · ✅ArrayList扩容机制
- 概念卡:概念卡片:HashMap底层原理 · 概念卡片:ArrayList与LinkedList · 概念卡片:ConcurrentHashMap演进
- 相关:概念卡片:CAS乐观锁与原子类(CHM1.8 的 CAS 基础)
- 域地图:A00-百科/Java后端/Java后端