一、为什么 Java 集合要细分这么多类型?
1. 核心底层数据结构不同,性能差异巨大
不同集合底层基于数组、链表、红黑树、哈希表、跳表实现,增删改查时间复杂度天差地别:
- 数组:随机查询快,中间插入删除慢;
- 链表:头尾增删快,随机查询慢;
- 哈希表:读写接近 O (1),无序;
- 红黑树:有序,查找 O (logn),插入删除平衡;
- 跳表:有序并发安全,性能均衡。
2. 特性需求不同(五大核心维度区分)
3. 业务场景多样化
业务需求千差万别:
- 单纯存有序可重复数据 → List
- 去重存储数据 → Set
- 键值映射、缓存、查找 → Map
- 队列、栈、任务排队 → Queue/Deque
如果只提供一种集合,会出现性能浪费、功能缺失、并发异常等问题,细分是性能、功能、安全三者权衡的结果。
二、Java 集合整体架构
集合分为两大根接口:
- List:有序、可重复
- Set:不可重复
- Queue/Deque:队列、双端队列
第一部分:List 系列(有序、可重复、支持索引)
通用特点
1. ArrayList
底层
动态数组(Object []),初始容量 10,扩容 1.5 倍。
时间复杂度
- 查询 get(i):O (1)(数组随机访问极强)
- 尾部新增:O (1)(无扩容);扩容 O (n)
- 中间 / 头部插入、删除:O (n)(需要数组拷贝移位)
线程安全
非线程安全,多线程读写会并发异常。
适用场景(最常用)
不适合
频繁在集合头部、中间插入 / 删除;超大集合频繁扩容。
2. LinkedList
底层
双向链表,不支持数组随机访问,无扩容概念。
时间复杂度
- 查询 get(i):O (n)(需要从头 / 尾遍历找节点)
- 头尾增删:O (1)
- 中间增删:O (n)(需要先遍历定位节点)
额外功能
实现 Deque 接口,可当队列、栈、双端队列使用。
线程安全
非线程安全。
适用场景
不适合
大量随机索引查询(循环 get 会极度缓慢)。
3. Vector
底层
动态数组,初始容量 10,扩容 2 倍。
核心特点
所有方法加synchronized同步锁,线程安全;性能极差。
适用场景
老旧遗留项目兼容,新项目完全不推荐,并发场景用 CopyOnWriteArrayList 替代。
4. Stack(Vector 子类,废弃)
基于 Vector 实现栈,push/pop/peek,同步锁性能差。
替代方案
Deque 接口实现类(ArrayDeque)官方推荐做栈。
5. CopyOnWriteArrayList
底层
数组,写时复制机制:修改元素时复制一份新数组操作,完成替换原数组;读不加锁。
特点
- 读极快,写极慢;
- 线程安全;
- 遍历不会并发修改异常;
适用场景
读多写极少的并发场景:配置缓存、白名单、常量列表;
不适合
高频增删改场景,每次写复制数组内存开销巨大。
第二部分:Set 系列(不可重复,无索引)
通用特点
元素唯一,自动去重;没有索引,不能通过下标取值;判断重复依靠 equals() + hashCode()。
1. HashSet
底层
哈希表(数组 + 链表 + 红黑树),基于 HashMap 实现,元素存到 Map 的 key。
特性
线程安全
非线程安全。
适用场景
2. LinkedHashSet
底层
哈希表 + 双向链表(继承 HashSet,基于 LinkedHashMap)。
特性
适用场景
3. TreeSet
底层
红黑树(基于 TreeMap)。
特性
适用场景
4. CopyOnWriteArraySet
底层
封装 CopyOnWriteArrayList 实现。
特性
线程安全,读快写慢,有序,元素可重复?底层自动去重。
适用场景
并发环境下读多写少、需要去重的有序集合;极少使用。
5. ConcurrentSkipListSet
底层
跳表,并发安全有序 Set。
特性
多线程并发读写性能远优于 TreeSet,自动排序;
适用场景
高并发下需要有序、去重的数据存储;分布式本地有序计数器。
第三部分:Queue / Deque 队列、双端队列(存取有规则)
Queue:单向队列,先进先出 FIFO; Deque:双端队列,可头尾操作,可做栈 LIFO。
1. ArrayDeque(最推荐队列 / 栈)
底层
循环数组,无容量限制自动扩容。
特性
适用场景
2. LinkedList(充当 Queue/Deque)
双向链表实现队列,头尾操作 O (1),随机查询慢。
适用场景
队列数据频繁扩容、长度波动极大,不适合 ArrayDeque;极少使用。
3. PriorityQueue 优先队列
底层
最小堆(数组实现二叉堆)。
特性
适用场景
4. 并发阻塞队列(java.util.concurrent,多线程生产者消费者)
(1) ArrayBlockingQueue
底层固定长度数组,有界阻塞队列;必须指定容量。 适用:生产消费速度可控,防止无限堆积,线程池任务队列。
(2) LinkedBlockingQueue
单向链表,无界 / 有界可选,读写两把锁,并发性能高于 ArrayBlockingQueue; 适用:线程池默认队列、通用生产者消费者。
(3) SynchronousQueue
不存储元素,插入操作必须等待对应删除操作,直接交付; 适用:任务必须立刻处理,无缓冲,Executors.newCachedThreadPool 使用。
(4) DelayQueue
延迟阻塞队列,元素实现 Delayed 接口,到期才能取出; 适用:定时任务、超时订单、缓存过期清理。
(5) ConcurrentLinkedQueue / ConcurrentLinkedDeque
无锁并发队列,基于 CAS,非阻塞;高并发读写性能极高; 适用:高并发消息排队,不需要阻塞等待。
第四部分:Map 键值对集合(Key 唯一,存储映射关系)
通用特点
存储 key-value 键值对;key 不可重复,value 可重复;key 重复会覆盖旧 value。
1. HashMap(日常最常用)
底层
哈希表:数组 + 链表 + 红黑树,JDK8 优化,链表长度≥8 转红黑树。
特性
适用场景
2. LinkedHashMap
底层
哈希表 + 双向链表。
特性
适用场景
3. TreeMap
底层
红黑树。
特性
适用场景
4. Hashtable(淘汰)
特性
全方法 synchronized 同步,线程安全;key 和 value 都不允许 null;性能极差。 新项目禁用,并发用 ConcurrentHashMap。
5. ConcurrentHashMap(高并发首选 Map)
底层
JDK7 分段锁、JDK8 CAS + 同步锁 + 红黑树;
特性
适用场景
多线程环境下的键值缓存:全局配置、多线程共享映射、本地并发计数器。
6. Properties
继承 Hashtable,专门存储字符串键值对,支持读写 properties 配置文件。 适用:读取项目配置文件(数据库配置、常量配置)。
7. ConcurrentSkipListMap
底层跳表,并发安全、key 自动排序; 适用:高并发下需要有序键值映射,替代 TreeMap 并发场景。
三、各集合选型速查表(业务直接对照)
单列集合 Collection
表格
| 单线程,查询遍历多,有序可重复 | ArrayList | LinkedList |
| 频繁头尾增删,很少索引查询 | LinkedList / ArrayDeque | ArrayList |
| 多线程读多写少,有序列表 | CopyOnWriteArrayList | Vector |
| 数据去重,不要求顺序 | HashSet | TreeSet |
| 数据去重,保留插入顺序 | LinkedHashSet | TreeSet |
| 数据去重,自动排序、区间查询 | TreeSet | HashSet |
| 栈、普通 FIFO 队列 | ArrayDeque | Stack、LinkedList |
| 任务按优先级执行 | PriorityQueue | ArrayDeque |
| 多线程生产者消费者阻塞队列 | ArrayBlockingQueue / LinkedBlockingQueue | LinkedList |
| 高并发无锁消息队列 | ConcurrentLinkedQueue | ArrayBlockingQueue |
双列集合 Map
表格
| 单线程键值缓存,追求性能 | HashMap |
| 键值需要插入顺序 / LRU 缓存 | LinkedHashMap |
| key 自动排序、区间查询 | TreeMap |
| 多线程并发读写映射缓存 | ConcurrentHashMap |
| 读取 properties 配置文件 | Properties |
| 高并发 + key 有序 | ConcurrentSkipListMap |





