Java 集合框架(Java Collections Framework) 是 Java 中最核心、最常用的 API 之一,几乎所有项目都会大量使用它。
下面从核心组件、类图关系、使用场景、性能对比、线程安全等角度给你一个清晰、实用的全面总结,适合从入门到面试/项目实战复习。
1. 集合框架整体架构(2025 视角)
Collection(接口) Map(接口)
├── List(接口) ├── HashMap
│ ├── ArrayList ├── LinkedHashMap
│ ├── LinkedList ├── TreeMap
│ └── Vector(基本废弃) ├── Hashtable(基本废弃)
│ ├── ConcurrentHashMap(高并发首选)
│ └── WeakHashMap / IdentityHashMap 等
├── Set(接口)
│ ├── HashSet
│ ├── LinkedHashSet
│ └── TreeSet
└── Queue(接口)
├── PriorityQueue
├── ArrayDeque(双端队列)
└── ConcurrentLinkedQueue 等
两大顶层接口:
- Collection:表示一组对象(元素集合)
- Map:表示键-值对映射(key → value)
2. 核心实现类对比表(最常用)
| 集合类 | 数据结构 | 是否有序 | 是否允许重复 | 是否线程安全 | 随机访问效率 | 插入/删除效率 | 适用场景(最常见用法) | 推荐使用场景 |
|---|---|---|---|---|---|---|---|---|
| ArrayList | 动态数组 | 有序 | 允许 | 否 | O(1) | O(n) | 普通列表、频繁随机访问 | ★★★★★ |
| LinkedList | 双向链表 | 有序 | 允许 | 否 | O(n) | O(1) | 频繁头尾增删、队列/栈、实现Deque | ★★★☆☆ |
| HashSet | HashMap(key) | 无序 | 不允许 | 否 | — | 平均 O(1) | 去重、查重、唯一元素集合 | ★★★★☆ |
| LinkedHashSet | HashMap+链表 | 插入顺序 | 不允许 | 否 | — | 平均 O(1) | 需要保持插入顺序的去重集合 | ★★★☆☆ |
| TreeSet | 红黑树 | 自然/比较器顺序 | 不允许 | 否 | — | O(log n) | 需要排序、范围查询、去重+有序 | ★★★★☆ |
| HashMap | 数组+链表+红黑树(JDK8+) | 无序 | 键不允许重复 | 否 | O(1) 平均 | O(1) 平均 | 键值对存储、缓存、配置、计数 | ★★★★★ |
| LinkedHashMap | HashMap+双向链表 | 插入/访问顺序 | 键不允许重复 | 否 | O(1) 平均 | O(1) 平均 | LRU 缓存、按插入/访问顺序遍历 | ★★★★☆ |
| TreeMap | 红黑树 | 键的自然/比较器顺序 | 键不允许重复 | 否 | O(log n) | O(log n) | 需要按键排序的映射、范围查询 | ★★★★☆ |
| ConcurrentHashMap | 数组+链表+红黑树 | 无序 | 键不允许重复 | 是(高并发) | O(1) 平均 | O(1) 平均 | 多线程并发读写、缓存、计数器 | ★★★★★ |
| PriorityQueue | 堆(二叉堆) | 优先级顺序 | 允许 | 否 | — | O(log n) | 优先级队列、Top-K、Dijkstra、Huffman编码 | ★★★★☆ |
| ArrayDeque | 循环数组 | 有序 | 允许 | 否 | O(1) | O(1) 均摊 | 高效双端队列、栈、队列(推荐替代 LinkedList) | ★★★★★ |
3. 最常见使用场景快速对照表
| 需求 | 首选集合类 | 次选 / 备选 | 为什么首选 |
|---|---|---|---|
| 普通列表,频繁 get/set | ArrayList | LinkedList | 随机访问最快 |
| 频繁在头部/尾部增删 | ArrayDeque | LinkedList | ArrayDeque 性能更好、内存更省 |
| 需要去重,不关心顺序 | HashSet | LinkedHashSet | HashSet 最快 |
| 去重 + 保持插入顺序 | LinkedHashSet | — | 兼顾去重和顺序 |
| 去重 + 自动排序 | TreeSet | — | 天然有序 + 范围查询能力 |
| 普通键值对存储 | HashMap | LinkedHashMap | 最高性能 |
| 按插入顺序 / 访问顺序遍历 | LinkedHashMap | — | 天然支持 LRU |
| 多线程高并发读写 | ConcurrentHashMap | Collections.synchronizedMap | 并发性能远超 synchronized |
| 需要按键排序的映射 | TreeMap | — | 红黑树实现,key 有序 |
| 优先级任务调度 / Top-K | PriorityQueue | — | 堆结构,poll() 总是最小/最大 |
| 实现 LRU 缓存 | LinkedHashMap(access-order=true) | Caffeine / Guava Cache | 原生支持 access-order 模式 |
4. 线程安全集合快速选择
| 场景 | 推荐方案 | 备注 / 性能对比 |
|---|---|---|
| 读多写少 | CopyOnWriteArrayList / CopyOnWriteArraySet | 写慢读快,适合事件监听器、配置快照 |
| 高并发读写 | ConcurrentHashMap | 分段锁 / CAS,性能极高 |
| 简单同步 | Collections.synchronizedXXX | 简单但锁粒度大,性能差 |
| 队列 | ConcurrentLinkedQueue / BlockingQueue | 非阻塞 / 阻塞队列选择 |
| 优先级队列 | PriorityBlockingQueue | 线程安全的 PriorityQueue |
5. 面试 / 项目中最常问的点(建议背诵)
- ArrayList 和 LinkedList 区别?底层结构?适用场景?
- HashMap JDK7 vs JDK8 的区别?为什么引入红黑树?
- HashMap 为什么线程不安全?ConcurrentHashMap 如何实现线程安全?
- HashSet 如何保证唯一性?底层依赖什么?
- LinkedHashMap 如何实现 LRU?
- TreeMap / TreeSet 的排序依据是什么?如何自定义比较器?
- 为什么推荐用迭代器删除元素,而不是直接 remove?
- fail-fast vs fail-safe 机制区别?
- Collections 工具类的常用方法(sort、binarySearch、shuffle、unmodifiableXXX 等)
6. 推荐学习与练习顺序
- 熟练掌握 ArrayList / HashMap / HashSet 的增删改查
- 搞懂 HashMap 的 put/get 过程(JDK8+)
- 实现一个简单的 LRUCache(用 LinkedHashMap)
- 用 PriorityQueue 实现 Top-K 问题
- 对比 ArrayDeque vs LinkedList 的性能(压测)
- 多线程场景下用 ConcurrentHashMap 做计数器
如果你想深入某个具体集合类的源码分析、使用示例、性能压测代码、常见面试题解析,或者想看某个场景的完整代码实现(比如 LRU、Top-K、去重排序等),可以告诉我,我可以继续展开!