---
title: "00-容器选型总对比"
created: 2026-09-01
tags:
- Java
---
# 容器选型总对比
> [!note] 定位说明
> 本篇是 02-Java容器 的收官对比篇:把四大系列散落各篇的选型知识收拢成"一张总表 + 一张复杂度表 + 一套线程安全方案"。速查用本篇,深读回各系列([[00-List总览|List]] / [[00-Set总览|Set]] / [[00-Queue和Deque总览|Queue]] / [[00-Map总览|Map]])。
## 一、两大体系全景
```mermaid
graph LR
subgraph Collection["Collection(单值)"]
L["List
有序可重复"]
S["Set
唯一"]
Q["Queue/Deque
队列/双端"]
end
M["Map(键值对)
键唯一值可重复"]
ROOT["Iterable"]
ROOT --> Collection
ROOT -.->|"独立体系(不是 Collection)"| M
L --> AL["ArrayList(默认)"] & LL["LinkedList"] & V["Vector(遗留)"]
S --> HS["HashSet(默认)"] & LHS["LinkedHashSet(保序)"] & TS["TreeSet(排序)"]
Q --> PQ["PriorityQueue(堆)"]
Q --> AD["ArrayDeque(双端/栈)"]
M --> HM["HashMap(默认)"] & LHM["LinkedHashMap(LRU)"] & TM["TreeMap(排序)"]
```
一句话框架:**Collection 家族"装单个元素",Map 家族"装键值对"**;`Map` 不是 `Collection` 的子接口,它是平行的另一棵树(但 `values()` 返回 Collection、`keySet()` 返回 Set,两者互通)。
## 二、常用实现一张总表
| 实现类 | 所属族 | 底层结构 | 顺序 | 去重/键判定 | null 支持 | 平均复杂度 | 一句话定位 |
| --- | --- | --- | --- | --- | --- | --- | --- |
| ArrayList | List | 动态数组 | 插入序 | 可重复 | ✅ | 查 O(1) 改 O(n) | **默认 List** |
| LinkedList | List+Deque | 双向链表 | 插入序 | 可重复 | ✅ | 头尾 O(1) 查 O(n) | 头尾操作/当队列栈(但栈首选 ArrayDeque) |
| Vector | List | 动态数组+方法锁 | 插入序 | 可重复 | ✅ | 查 O(1) 锁开销大 | **遗留,不用** |
| HashSet | Set | 哈希表(HashMap) | 无序 | hashCode+equals | 1 个 null | O(1) | **默认 Set** |
| LinkedHashSet | Set | 哈希表+双向链表 | 插入序 | 同 HashSet | 1 个 null | O(1) 微开销 | 去重且保序 |
| TreeSet | Set | 红黑树(TreeMap) | 排序 | compareTo/compare==0 | ❌ | O(log n) | 排序+范围查询 |
| ArrayDeque | Deque | 循环数组 | 无序 | — | ❌ | 头尾均摊 O(1) | **栈/双端首选** |
| PriorityQueue | Queue | 二叉最小堆 | 优先级出队 | 可重复 | ❌ | O(log n) | Top K/调度 |
| HashMap | Map | 数组+链表+红黑树 | 无序 | hashCode+equals | 1 null 键 | O(1) | **默认 Map** |
| LinkedHashMap | Map | 哈希表+双向链表 | 插入/访问序 | 同 HashMap | 1 null 键 | O(1) 微开销 | LRU 现成地基 |
| TreeMap | Map | 红黑树 | 键排序 | compareTo==0 | ❌ null 键 | O(log n) | 排序映射+范围查询 |
| Hashtable | Map | 哈希表+方法锁 | 无序 | 同 HashMap | ❌ | O(1) 锁开销大 | **遗留,用 ConcurrentHashMap** |
## 三、复杂度速查
| 操作 | ArrayList | LinkedList | HashSet/HashMap | TreeSet/TreeMap | ArrayDeque | PriorityQueue |
| --- | --- | --- | --- | --- | --- | --- |
| 随机访问 | O(1) | O(n) | — | O(log n) | — | — |
| 头部插/删 | O(n) | O(1) | — | — | O(1) | — |
| 尾部插/删 | O(1) 均摊 | O(1) | — | — | O(1) | O(log n) offer |
| 按内容查找 | O(n) | O(n) | O(1) | O(log n) | O(n) | O(n) |
| 插入(中间) | O(n) | O(n)(定位 O(n) + 改指针 O(1)) | — | — | — | — |
| 取最值 | O(n) | O(n) | — | O(log n)(first/last 是 O(1)?核对点:TreeMap firstKey 走最左节点,O(log n)) | — | O(1) peek |
## 四、线程安全方案对照
| 方案 | 原理 | 代价 | 适用 |
| --- | --- | --- | --- |
| `Vector` / `Hashtable` | 方法级 `synchronized`(遗留) | 粗粒度锁,读读互斥 | 只剩旧代码兼容 |
| `Collections.synchronizedXxx()` | 包装器,同粗粒度锁 | 与 Vector 相当 | 任意容器快速加锁,语义清晰 |
| `CopyOnWriteArrayList` | 写时复制新数组 | 写贵(复制全量),读完全无锁 | **读多写极少**(监听器列表、配置缓存) |
| `ConcurrentHashMap` | JDK 8:CAS + synchronized 锁单桶 | 细粒度,并发度高 | **并发 Map 唯一正解** |
| `ConcurrentLinkedQueue` | 无锁 CAS 链表 | 无阻塞 | 高并发无界队列 |
| `BlockingQueue` 家族 | 锁 + 条件阻塞 | 阻塞语义 | 生产者-消费者(`ArrayBlockingQueue`/`LinkedBlockingQueue`) |
> 记忆主线:**遗留类(Vector/Hashtable/Stack)三兄弟全部淘汰**;替代思路都是"把锁变小"——要么锁单个桶(ConcurrentHashMap),要么干脆不锁靠复制(CopyOnWriteArrayList),要么无锁 CAS。阻塞与并发细节等 03-Java并发 分区展开。
## 五、选型三问(收束)
1. **装什么形态?** 单值 → Collection 三族;键值对 → Map 三族。
2. **要什么顺序?** 无所谓 → HashSet/HashMap(默认);保插入序 → Linked 系;要排序/范围 → Tree 系。
3. **什么环境?** 单线程 → 上面的默认答案;多线程 → 第四节并发方案,且细节留给并发分区。
高频翻车点都记在对应系列总览里:`remove` 重载歧义与 `Arrays.asList` 定长坑见 [[00-List总览|00-List总览]],`retainAll` 就地修改见 [[00-Set总览|00-Set总览]],`merge`/`getOrDefault` 套路见 [[00-Map总览|00-Map总览]]。
---
⬅️ [[07-红黑树|红黑树]] 🏠 [[00-Java|00-Java]] ➡️ [[01-容器高频面试题|01-容器高频面试题]]