Collections 工具类
问题
Collections 工具类提供了哪些有用的方法?如何创建不可变集合?
答案
排序与查找
SortAndSearch.java
List<Integer> list = new ArrayList<>(Arrays.asList(3, 1, 4, 1, 5, 9));
// 排序(原地修改,TimSort 算法,稳定排序)
Collections.sort(list); // [1, 1, 3, 4, 5, 9]
Collections.sort(list, Comparator.reverseOrder()); // [9, 5, 4, 3, 1, 1]
list.sort(Comparator.naturalOrder()); // JDK 8+ List 自带 sort
// 二分查找(列表必须已排序)
Collections.sort(list);
int index = Collections.binarySearch(list, 4); // 返回下标
// 最大/最小值
int max = Collections.max(list);
int min = Collections.min(list);
// 反转、洗牌、旋转
Collections.reverse(list); // 反转
Collections.shuffle(list); // 随机打乱
Collections.rotate(list, 2); // 循环右移 2 位
Collections.swap(list, 0, 1); // 交换两个位置的元素
不可变集合
UnmodifiableCollections.java
// Collections.unmodifiableXxx():返回不可修改的视图
List<String> mutable = new ArrayList<>(Arrays.asList("a", "b", "c"));
List<String> immutable = Collections.unmodifiableList(mutable);
// immutable.add("d"); // UnsupportedOperationException
mutable.add("d"); // 注意:修改原集合会影响视图!
// JDK 9+ List.of() / Map.of():创建真正不可变的集合
List<String> list = List.of("a", "b", "c"); // 不可变,不允许 null
Map<String, Integer> map = Map.of("a", 1, "b", 2); // 不可变,不允许 null
Set<String> set = Set.of("a", "b", "c"); // 不可变,不允许 null
// JDK 10+ List.copyOf():从已有集合创建不可变副本
List<String> copy = List.copyOf(mutable); // 独立副本,原集合修改不影响
| 方式 | 可修改 | null 支持 | 与原集合关系 |
|---|---|---|---|
Collections.unmodifiableList() | 不可修改视图 | 允许 | 共享数据 |
List.of()(JDK 9+) | 不可变 | 不允许 | 独立 |
List.copyOf()(JDK 10+) | 不可变 | 不允许 | 独立副本 |
线程安全包装
SynchronizedCollections.java
// 包装为线程安全的集合(所有方法加 synchronized)
List<String> syncList = Collections.synchronizedList(new ArrayList<>());
Map<String, Integer> syncMap = Collections.synchronizedMap(new HashMap<>());
Set<String> syncSet = Collections.synchronizedSet(new HashSet<>());
// 注意:迭代时仍需手动同步
synchronized (syncList) {
for (String item : syncList) {
// ...
}
}
性能更好的替代方案
Collections.synchronizedXxx 锁粒度太粗(全表锁),推荐使用 java.util.concurrent 包的并发集合:
ConcurrentHashMap替代synchronizedMapCopyOnWriteArrayList替代synchronizedList(读多写少)
其他实用方法
// 空集合(不可变的空集合,避免返回 null)
List<String> empty = Collections.emptyList();
Map<String, Integer> emptyMap = Collections.emptyMap();
// 单元素集合
List<String> single = Collections.singletonList("only");
Map<String, Integer> singleMap = Collections.singletonMap("key", 1);
// 填充
Collections.fill(list, "default"); // 所有元素替换为 "default"
// 频率统计
int count = Collections.frequency(list, "target");
// 不相交判断
boolean disjoint = Collections.disjoint(list1, list2); // true = 无交集
常见面试问题
Q1: Collections 和 Collection 的区别?
答案:
Collection:接口,是 List、Set、Queue 的父接口,定义了集合的基本操作Collections:工具类,提供排序、查找、同步包装等静态方法
Q2: Collections.sort() 使用的什么排序算法?
答案:
TimSort 算法(JDK 7+ 默认),结合了归并排序和插入排序:
- 时间复杂度:最好 、平均/最坏
- 稳定排序
- 对部分有序的数据特别高效
Q3: 如何返回一个空集合而不是 null?
答案:
// ✅ 推荐:返回空集合
public List<User> findUsers() {
List<User> users = userDao.query();
return users != null ? users : Collections.emptyList();
// 或 JDK 9+
// return users != null ? users : List.of();
}
// ❌ 不推荐:返回 null,调用方必须判空
这遵循了 Effective Java 的建议:"返回空集合或数组,而不是 null"。