Java Collection 体系与使用场景整理
本文从抽象层级、接口设计、实际使用场景 三个角度,系统说明什么是 Collection,什么时候"面向 Collection 创建对象",什么时候应直接使用 List,以及何时选择其它集合类型(Set、Queue、Map 等)。
一、什么是 Collection
1. Collection 的本质
Collection<E> 是 Java 集合框架(Java Collections Framework, JCF)中最基础的集合接口之一,表示:
一组元素(element)的抽象集合
它只关心:
- 是否能存元素
- 是否能遍历
- 是否能删除
- 是否包含某元素
而不关心:
- 是否有顺序
- 是否允许重复
- 是否支持索引
2. Collection 在体系中的位置
text
Iterable
↑
Collection
↑
├── List
├── Set
└── Queue
Collection是List/Set/Queue的共同父接口 ,但 不包含索引、顺序、唯一性等语义。
二、为什么要有 Collection 这种"看起来没什么用"的接口
1. 抽象层面的意义
Collection 的存在是为了:
- 统一抽象:对"元素集合"进行最小能力抽象
- 解耦实现 :调用方不关心底层是
ArrayList、LinkedList、HashSet - 支持多态:同一段代码可处理多种集合实现
示例:
java
void process(Collection<String> c) {
for (String s : c) {
System.out.println(s);
}
}
这段代码:
- 可以接收
ArrayList - 可以接收
HashSet - 可以接收
LinkedList
2. Collection 的"能力边界"
Collection 刻意不提供以下能力:
- 索引访问(
get(int)) - 保证顺序
- 保证唯一性
因为:
- 并非所有集合都有这些语义
- 强行放入接口会破坏接口隔离原则(ISP)
三、什么时候"创建 Collection"
重要
Collection 是接口,不能直接 new
真正创建的是:
java
Collection<String> c = new ArrayList<>();
这里的含义是:
- 编译期类型 :
Collection - 运行期类型 :
ArrayList
适合使用 Collection 作为声明类型的场景
场景 1:方法参数(最典型)
java
void saveAll(Collection<User> users) {
...
}
理由:
- 方法不依赖"索引/顺序/唯一性"
- 调用方自由选择
List/Set
java
List<User> l = new ArrayList<>();
l.add("b");
l.add("c");
saveAll(l);
这是 最推荐 的使用方式(就是多态的体现)。

场景 2:返回值只表达"一组元素"
java
Collection<Order> findOrders() {
return new ArrayList<>();
}
调用方:
- 只能遍历、判断、删除
- 不会错误依赖具体实现
场景 3:业务逻辑不关心集合语义
java
Collection<String> tags = new HashSet<>();
当你只需要:
- 存
- 遍历
- 不关心顺序和索引
四、什么时候必须使用 List
List 的核心语义
List<E> 表示:
有序、可重复、可按索引访问的集合
它在 Collection 基础上增加了:
get(int index)set(int, E)add(int, E)
必须使用 List 的典型场景
场景 1:需要索引访问
java
List<String> list = new ArrayList<>();
String first = list.get(0);
如果你需要 get(i),就不应该使用 Collection 声明。
场景 2:需要顺序语义
java
List<String> steps = List.of("init", "load", "run");
顺序有业务含义(流程、步骤、时间线)。
场景 3:与 UI / JSON / DTO 强绑定
- 前端列表
- JSON array
- Excel 行
这些天然是 有序结构 ,应使用 List。
List 的常见实现选择
| 实现 | 适用场景 |
|---|---|
ArrayList |
读多写少、随机访问多(默认首选) |
LinkedList |
频繁头尾插入/删除(但实际很少需要) |
五、什么时候使用 Set
Set 的核心语义
Set<E> 表示:
不允许重复元素的集合
典型使用场景
- 去重
- 成员检测(contains)
- 数学集合语义
示例:
java
Set<String> users = new HashSet<>();
常见实现:
HashSet:不保证顺序(最快)LinkedHashSet:保持插入顺序TreeSet:排序集合
六、什么时候使用 Queue / Deque
Queue / Deque 的语义
- Queue:队列(FIFO)
- Deque:双端队列
使用场景
- 任务队列
- 消息缓冲
- BFS / 滑动窗口
示例:
java
Queue<Task> q = new ArrayDeque<>();
七、Map 为什么不属于 Collection
Map 的本质
Map<K, V> 表示:
键值对映射,不是"元素集合"
所以:
- 不继承
Collection - 但可以通过
keySet()/values()/entrySet()间接使用Collection
八、总结
1. 面向接口编程
声明用接口,实现用具体类
java
List<String> list = new ArrayList<>();
Collection<String> c = new ArrayList<>();
2. 用"最小能力接口"
- 需要索引 →
List - 需要去重 →
Set - 只需遍历 →
Collection
3. 不要因为"实现是 ArrayList"就暴露 List
java
// 不推荐
public ArrayList<String> getData() { ... }
// 推荐
public List<String> getData() { ... }
九、一句话总结
- Collection:只表示"一堆元素",用于抽象、解耦、通用逻辑
- List:当顺序和索引是业务语义的一部分
- Set:当唯一性是业务约束
- Queue/Deque:当访问顺序受限(FIFO/LIFO)
- Map:当数据是"键 → 值"关系
接口表达"你需要什么能力",实现类决定"怎么做到"。