跳到主要内容

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 替代 synchronizedMap
  • CopyOnWriteArrayList 替代 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+ 默认),结合了归并排序和插入排序:

  • 时间复杂度:最好 O(n)O(n)、平均/最坏 O(nlogn)O(n \log n)
  • 稳定排序
  • 对部分有序的数据特别高效

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"。

相关链接