- 核心概念:
Collection是什么?它和Collections有什么区别? - 整体架构图:
Collection在整个集合框架中的位置。 - 主要接口详解:
List,Set,Queue的特点和常用实现类。 - 遍历方式:如何高效地遍历集合。
- 常用工具类:
Collections类提供了哪些静态方法。 - 总结与选择:如何根据业务场景选择合适的集合。
核心概念:Collection vs Collections
这是一个非常常见的面试题,也是初学者容易混淆的地方。

java.util.Collection
- 它是一个接口,位于集合框架的顶层。
- 它是
List,Set,Queue这三个核心接口的父接口。 - 它定义了所有单列集合(存储一组对象)最共有的方法,
add(E e): 添加元素remove(Object o): 删除元素contains(Object o): 判断是否包含元素size(): 获取元素个数iterator(): 获取迭代器,用于遍历集合isEmpty(): 判断集合是否为空
- 注意:
Collection接口本身不直接提供实现,我们通常使用的是它的子接口(如List)的实现类(如ArrayList)。
java.util.Collections
- 它是一个工具类,里面包含的都是静态方法。
- 它提供了一系列对
Collection或Map进行操作的算法和工具方法,- 排序:
sort(List<T> list) - 查找:
binarySearch(List<? extends Comparable<? super T>> list, T key) - 线程安全化:
synchronizedList(List<T> list) - 创建不可变集合:
unmodifiableList(List<? extends T> list) - 填充:
fill(List<? super T> list, T obj)
- 排序:
一句话总结:
Collection是一个接口,是集合的“祖宗”。Collections是一个工具类,是集合的“工具箱”。
整体架构图
理解了 Collection 的位置,再看下面的架构图就清晰多了。
- 最顶层:
Iterable接口,这是整个集合框架的“根”,实现了这个接口的类就可以使用for-each循环。Collection继承了Iterable。 - 核心接口:
Collection: 所有单列集合的父接口。Map: 存储键值对 的集合,不属于Collection体系,但同样是集合框架的核心部分。
- 三大子接口:
List: 有序、可重复。Set: 无序(指存取顺序)、不可重复。Queue: 队列,遵循先进先出 的原则。
- 实现类:就是我们在日常编码中真正使用的类,如
ArrayList,HashSet,HashMap等。
主要接口详解
List 接口
特点:有序(存储顺序和取出顺序一致)、可重复(允许存储 null 值)。
| 实现类 | 底层结构 | 特点 | 适用场景 |
|---|---|---|---|
ArrayList |
动态数组 | 查询快(随机访问 O(1)) 增删慢(需要移动元素 O(n)) 非线程安全 |
最常用,适用于元素数量不固定、需要频繁随机访问的场景,如读取列表数据。 |
LinkedList |
双向链表 | 查询慢(需要遍历 O(n)) 增删快(只需修改指针 O(1)) 非线程安全 |
适用于需要频繁在头部或中间插入/删除元素的场景,如实现队列、栈。 |
Vector |
动态数组 | 功能与 ArrayList 相同线程安全(但性能差,已不推荐使用) |
老代码中可能见到,新项目应使用 Collections.synchronizedList(new ArrayList<>()) 或 CopyOnWriteArrayList。 |
示例代码:

import java.util.ArrayList;
import java.util.List;
List<String> names = new ArrayList<>();
names.add("Alice");
names.add("Bob");
names.add("Alice"); // 允许重复
names.add(0, "Charlie"); // 在指定位置插入
System.out.println(names.get(1)); // 输出: Alice
System.out.println(names.contains("Bob")); // 输出: true
Set 接口
特点:无序(指存取顺序不保证一致)、不可重复(不能存储重复元素)。Set 的具体实现类决定了其元素的“无序”程度。
| 实现类 | 底层结构 | 特点 | 适用场景 |
|---|---|---|---|
HashSet |
哈希表 (HashMap) | 存取顺序不一致(无序) 查找、添加、删除速度快(平均 O(1)) 非线程安全 |
最常用,适用于要求不重复、不关心顺序的场景,如去重、作为键的集合。 |
LinkedHashSet |
哈希表 + 链表 | 有序(按插入顺序) 继承 HashSet,性能略低于 HashSet非线程安全 |
既要保证元素不重复,又需要保持插入顺序的场景,如记录最近访问的用户。 |
TreeSet |
红黑树 (TreeMap) | 排序(默认自然排序,或指定 Comparator) 查找、添加、删除速度较快(O(log n)) 非线程安全 |
需要对元素进行排序的场景,如按分数排名。 |
注意:HashSet 和 LinkedHashSet 要求元素必须重写 equals() 和 hashCode() 方法;TreeSet 要求元素必须实现 Comparable 接口或提供 Comparator。
示例代码:
import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;
// HashSet
Set<String> uniqueNames = new HashSet<>();
uniqueNames.add("David");
uniqueNames.add("Eve");
uniqueNames.add("David"); // 重复元素,不会被添加
System.out.println(uniqueNames); // 输出可能是 [Eve, David],顺序不确定
// TreeSet
Set<Integer> numbers = new TreeSet<>();
numbers.add(10);
numbers.add(5);
numbers.add(20);
System.out.println(numbers); // 输出 [5, 10, 20],自动排序
Queue 接口
特点:队列,遵循先进先出 的原则,常用于多线程场景。
| 实现类 | 特点 | 适用场景 |
|---|---|---|
LinkedList |
实现了 Queue 接口,可作为队列使用。 |
简单的 FIFO 队列。 |
PriorityQueue |
优先队列,不遵循 FIFO,而是按元素的“优先级”出队(默认自然排序)。 | 任务调度,如执行紧急任务。 |
ArrayBlockingQueue |
有界阻塞队列,基于数组,必须指定容量,当队列满/空时,put/take 操作会阻塞。 | 生产者-消费者模型,线程池。 |
LinkedBlockingQueue |
无界/有界阻塞队列,基于链表。 | 同上,容量可选,吞吐量通常高于 ArrayBlockingQueue。 |
示例代码:
import java.util.LinkedList;
import java.util.Queue;
Queue<String> queue = new LinkedList<>();
queue.add("A");
queue.add("B");
queue.add("C");
// FIFO
System.out.println(queue.poll()); // 移除并返回头部元素,输出: A
System.out.println(queue.peek()); // 查看头部元素但不移除,输出: B
遍历方式
有四种主要的遍历方式,推荐使用 迭代器 和 for-each 循环。
迭代器遍历(最安全、最通用)
可以在遍历时安全地删除元素。
List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
if ("B".equals(item)) {
iterator.remove(); // 安全删除
}
}
for-each 循环(最简洁、推荐)
底层也是使用的迭代器,不能在遍历时修改集合(会抛出 ConcurrentModificationException)。
for (String item : list) {
System.out.println(item);
}
传统 for 循环(适用于 List)
可以通过索引访问,但不适用于 Set 和 Queue。
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
JDK 8+ Stream API(函数式风格,功能强大)
非常适合进行复杂的链式操作,如过滤、映射、聚合。
list.stream()
.filter(s -> !"B".equals(s)) // 过滤掉 B
.forEach(System.out::println); // 打印
常用工具类 Collections
Collections 类提供了大量静态方法来操作集合。
List<Integer> numbers = new ArrayList<>(Arrays.asList(3, 1, 4, 1, 5)); // 1. 排序 Collections.sort(numbers); // [1, 1, 3, 4, 5] // 2. 二分查找(前提是集合已排序) int index = Collections.binarySearch(numbers, 4); // 返回 3 // 3. 反转 Collections.reverse(numbers); // [5, 4, 3, 1, 1] // 4. 打乱顺序 Collections.shuffle(numbers); // 5. 线程安全化 List<Integer> synchronizedList = Collections.synchronizedList(new ArrayList<>()); // 6. 创建不可变集合 List<Integer> unmodifiableList = Collections.unmodifiableList(numbers); // unmodifiableList.add(10); // 会抛出 UnsupportedOperationException
总结与选择:如何选择合适的集合?
这是一个非常重要的问题,选择合适的集合能让程序更高效、更健壮。
| 场景 | 首选 | 次选/原因 |
|---|---|---|
| 需要存储一组对象,允许重复,关心顺序 | ArrayList |
LinkedList (如果频繁在头部/中间增删) |
| 需要存储一组对象,不允许重复,不关心顺序 | HashSet |
LinkedHashSet (如果需要保持插入顺序) |
| 需要存储一组对象,不允许重复,需要排序 | TreeSet |
HashSet + 手动排序 (如果排序不频繁) |
| 需要实现 FIFO 队列 | LinkedList 或 ArrayBlockingQueue (多线程) |
LinkedList 简单,ArrayBlockingQueue 功能更强 |
| 需要实现优先队列 | PriorityQueue |
- |
| 需要键值对存储 | HashMap |
TreeMap (需要排序), LinkedHashMap (需要插入顺序) |
| 需要线程安全的集合 | ConcurrentHashMap, CopyOnWriteArrayList |
Collections.synchronizedXxx() (性能较差) |
希望这份详细的梳理能帮助你彻底理解 Java 中的 Collection!
