Collections 工具类
概述
Collections 是 java.util 包中针对集合(List、Set、Map 等)的工具类,提供大量静态方法,用于排序、查找、填充、同步包装、不可变视图以及空集合等常见操作。日常开发中,直接使用这些方法可以避免手写循环、减少出错,并统一处理线程安全与不可变需求。
前置知识
建议已掌握 集合概述与体系、List、Set、Map 详解与遍历。
基本用法
Collections 的所有方法都是静态方法,通过类名直接调用:
import java.util.Collections;
import java.util.List;
import java.util.ArrayList;
List<String> list = new ArrayList<>(List.of("C", "A", "B"));
Collections.sort(list); // 原地排序
// list 变为 [A, B, C]常用方法可按用途分为:排序与打乱、查找与极值、不可变与空集合、同步包装、其他工具。下面按类目说明并给出示例。
排序与打乱
sort / reverse / shuffle
| 方法 | 说明 |
|---|---|
sort(List<T> list) | 按元素自然顺序升序排序(元素需实现 Comparable) |
sort(List<T> list, Comparator<? super T> c) | 按指定 Comparator 排序 |
reverse(List<?> list) | 反转列表顺序(原地) |
shuffle(List<?> list) | 随机打乱列表顺序 |
List<String> list = new ArrayList<>(List.of("banana", "apple", "cherry"));
// 自然顺序(字典序)排序
Collections.sort(list);
// list: [apple, banana, cherry]
// 反转
Collections.reverse(list);
// list: [cherry, banana, apple]
// 随机打乱(可用于洗牌、随机抽样等)
Collections.shuffle(list);自定义排序时使用 Comparator:
// 按字符串长度排序
Collections.sort(list, Comparator.comparingInt(String::length));
// 降序
Collections.sort(list, Comparator.reverseOrder());提示
对 基本类型 的 List(如 List<Integer>),sort(list) 按数值大小排序;对自定义类,需实现 Comparable<T> 或传入 Comparator。详见 常用类 中的比较与排序。
查找与极值
binarySearch / min / max
| 方法 | 说明 |
|---|---|
binarySearch(List<? extends Comparable> list, T key) | 二分查找,列表必须已按自然顺序升序;找到返回索引,否则返回负的插入点减 1 |
binarySearch(List<? extends T> list, T key, Comparator<? super T> c) | 按指定 Comparator 的二分查找 |
min(Collection<? extends T> coll) | 按自然顺序取最小元素 |
max(Collection<? extends T> coll) | 按自然顺序取最大元素 |
min/max(Collection, Comparator) | 按指定 Comparator 取最小/最大 |
List<Integer> nums = new ArrayList<>(List.of(10, 20, 30, 40, 50));
// 二分查找:列表必须已升序
int index = Collections.binarySearch(nums, 30); // 2
int notFound = Collections.binarySearch(nums, 25); // 负数,表示插入点
// 极值
int min = Collections.min(nums); // 10
int max = Collections.max(nums); // 50注意
binarySearch 的前提是列表已按对应顺序排好。若未排序,结果未定义。先 Collections.sort(list) 再 binarySearch。
不可变与空集合
空集合
避免返回 null,用空集合表示「无元素」更安全:
| 方法 | 返回类型 | 说明 |
|---|---|---|
emptyList() | List<T> | 不可变的空 List |
emptySet() | Set<T> | 不可变的空 Set |
emptyMap() | Map<K,V> | 不可变的空 Map |
// 方法无结果时返回空集合,调用方无需判 null
public List<String> findNames(String filter) {
if (filter == null || filter.isBlank())
return Collections.emptyList();
// ...
return result;
}
// 调用方可以安全地遍历
for (String name : findNames("")) {
// 不会进入,也不会 NPE
}单元素集合
| 方法 | 说明 |
|---|---|
singletonList(T o) | 只含一个元素的不可变 List |
singleton(T o) | 只含一个元素的不可变 Set |
singletonMap(K key, V value) | 只含一个键值对的不可变 Map |
// 不可变单元素集合,常用于「仅允许一个值」的 API
Set<String> one = Collections.singleton("only");
List<Integer> single = Collections.singletonList(42);
Map<String, Integer> oneEntry = Collections.singletonMap("count", 1);不可变视图(unmodifiable*)
用现有集合包装成「只读」视图,修改原集合仍会反映到视图中,但对视图的写操作会抛出 UnsupportedOperationException:
| 方法 | 说明 |
|---|---|
unmodifiableList(List list) | 不可变 List 视图 |
unmodifiableSet(Set set) | 不可变 Set 视图 |
unmodifiableMap(Map map) | 不可变 Map 视图 |
List<String> mutable = new ArrayList<>(List.of("A", "B"));
List<String> readOnly = Collections.unmodifiableList(mutable);
readOnly.get(0); // "A" — 读可以
readOnly.add("C"); // 抛出 UnsupportedOperationException
mutable.add("C"); // 可以,且 readOnly 看到 [A, B, C]提示
若需要「完全不可变且与原集合无关」的副本,可先复制再包装:Collections.unmodifiableList(new ArrayList<>(original))。Java 9+ 也可使用 List.of()、Set.of()、Map.of() 等直接创建不可变集合。
同步包装(线程安全视图)
若要在多线程下对 List/Set/Map 做同步访问,可用 synchronized* 包装。每次读写都会在包装对象上加锁,保证线程安全但不是高性能方案:
| 方法 | 说明 |
|---|---|
synchronizedList(List list) | 线程安全的 List 视图 |
synchronizedSet(Set set) | 线程安全的 Set 视图 |
synchronizedMap(Map map) | 线程安全的 Map 视图 |
List<String> list = new ArrayList<>();
List<String> syncList = Collections.synchronizedList(list);
// 多线程下遍历时,必须对 syncList 做同步,否则可能 ConcurrentModificationException
synchronized (syncList) {
for (String s : syncList) {
// 使用 s
}
}注意
遍历同步包装的集合时,必须在 synchronized (syncList) 块内进行,否则迭代器与修改可能并发导致异常。高并发场景更推荐 ConcurrentHashMap 等并发集合。
其他常用方法
| 方法 | 说明 |
|---|---|
fill(List list, T obj) | 将列表中每个位置替换为 obj |
replaceAll(List list, T oldVal, T newVal) | 将列表中所有等于 oldVal 的元素替换为 newVal |
swap(List list, int i, int j) | 交换索引 i 与 j 的元素 |
rotate(List list, int distance) | 整体「旋转」:正数右移,负数左移 |
frequency(Collection c, Object o) | 元素 o 在集合中的出现次数 |
disjoint(Collection c1, Collection c2) | 两集合是否无交集(无公共元素返回 true) |
addAll(Collection c, T... elements) | 将多个元素一次性加入集合 |
List<String> list = new ArrayList<>(List.of("a", "b", "a", "c"));
Collections.replaceAll(list, "a", "A");
// list: [A, b, A, c]
int count = Collections.frequency(list, "A"); // 2
List<String> other = List.of("x", "y");
boolean noCommon = Collections.disjoint(list, other); // true
List<String> target = new ArrayList<>();
Collections.addAll(target, "one", "two", "three");
// target: [one, two, three]完整示例:排序与不可变返回
下面示例结合排序与不可变视图,实现一个「返回排序后只读列表」的用法:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class CollectionsDemo {
public static List<String> sortedNamesReadOnly(List<String> names) {
if (names == null || names.isEmpty())
return Collections.emptyList();
List<String> copy = new ArrayList<>(names);
Collections.sort(copy);
return Collections.unmodifiableList(copy);
}
public static void main(String[] args) {
List<String> raw = new ArrayList<>(List.of("张三", "李四", "王五"));
List<String> sorted = sortedNamesReadOnly(raw);
System.out.println(sorted); // [李四, 王五, 张三](按自然顺序)
// sorted.add("赵六"); // 会抛出 UnsupportedOperationException
}
}注意事项
- binarySearch 前必须保证列表已按对应顺序(自然顺序或 Comparator)排好序。
- unmodifiable* 是视图,底层集合被修改时视图内容会变;若要完全独立不可变,先复制再包装。
- synchronized* 遍历时需在
synchronized (包装对象)内进行,高并发更推荐专用并发集合。 - 返回「无元素」时优先用
emptyList()/emptySet()/emptyMap(),避免返回null造成 NPE。
提示
Java 9+ 的 List.of()、Set.of()、Map.of() 可直接创建不可变集合,无需先可变再包装;但 Collections 的 empty*、singleton*、unmodifiable* 在兼容老版本和接收已有集合做视图时仍然常用。