Collections 详解
一、Collections(JDK自带)
排序相关
List<Integer> list = new ArrayList<>(Arrays.asList(3, 1, 4, 1, 5, 9));
// 自然排序(升序)
Collections.sort(list);
// [1, 1, 3, 4, 5, 9]
// 自定义排序(降序)
Collections.sort(list, (a, b) -> b - a);
// [9, 5, 4, 3, 1, 1]
// 也可以用Comparator
Collections.sort(list, Comparator.reverseOrder());
// 对象排序(按年龄升序)
List<User> users = new ArrayList<>();
Collections.sort(users, Comparator.comparing(User::getAge));
// 多字段排序(先按年龄,再按名字)
Collections.sort(users,
Comparator.comparing(User::getAge)
.thenComparing(User::getName));
查找相关
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
// 最大值、最小值
int max = Collections.max(list); // 5
int min = Collections.min(list); // 1
// 自定义比较器找最大值(比如找名字最长的)
User oldest = Collections.max(users, Comparator.comparing(User::getName));
// 二分查找(前提:list必须已排序)
int index = Collections.binarySearch(list, 3); // 返回下标 2
// 统计某元素出现次数
List<String> strList = Arrays.asList("a", "b", "a", "c", "a");
int count = Collections.frequency(strList, "a"); // 3
操作相关
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
// 反转
Collections.reverse(list);
// [5, 4, 3, 2, 1]
// 随机打乱
Collections.shuffle(list);
// 用固定值填充整个list
Collections.fill(list, 0);
// [0, 0, 0, 0, 0]
// 拷贝(dest长度必须 >= src)
List<Integer> dest = new ArrayList<>(Arrays.asList(0, 0, 0, 0, 0));
List<Integer> src = Arrays.asList(1, 2, 3);
Collections.copy(dest, src);
// dest = [1, 2, 3, 0, 0]
// 整体替换(把list中所有的oldVal替换成newVal)
Collections.replaceAll(list, 0, 9);
// 循环移位(正数右移,负数左移)
List<Integer> rotateList = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
Collections.rotate(rotateList, 2);
// [4, 5, 1, 2, 3]
// 交换两个位置的元素
Collections.swap(list, 0, 4); // 交换下标0和4的元素
安全相关(重要!)
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3));
// ① 不可变集合 ------ 防止被外部修改
List<Integer> immutableList = Collections.unmodifiableList(list);
immutableList.add(4); // 抛出 UnsupportedOperationException
Map<String, Integer> immutableMap = Collections.unmodifiableMap(map);
Set<String> immutableSet = Collections.unmodifiableSet(set);
// ② 线程安全集合 ------ 多线程环境使用
List<Integer> syncList = Collections.synchronizedList(list);
Map<String, Integer> syncMap = Collections.synchronizedMap(map);
Set<String> syncSet = Collections.synchronizedSet(set);
// 注意:synchronizedList遍历时仍需手动加锁
synchronized (syncList) {
for (Integer i : syncList) {
System.out.println(i);
}
}
创建特殊集合
// 空集合(不可变,比new ArrayList()更轻量)
List<String> emptyList = Collections.emptyList();
Map<String, Integer> emptyMap = Collections.emptyMap();
Set<String> emptySet = Collections.emptySet();
// 单元素集合(不可变)
List<String> singleList = Collections.singletonList("only");
Map<String, Integer> singleMap = Collections.singletonMap("key", 1);
Set<String> singleSet = Collections.singleton("only");
// 重复N个元素的集合
List<String> nCopies = Collections.nCopies(5, "hello");
// ["hello", "hello", "hello", "hello", "hello"]
二、CollectionUtils(Apache Commons)
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.4</version>
</dependency>
判空(最常用)
List<String> list = null;
List<String> list2 = new ArrayList<>();
List<String> list3 = Arrays.asList("a", "b");
// isEmpty ------ null和空集合都返回true,不会空指针!
CollectionUtils.isEmpty(list); // true ← null也安全
CollectionUtils.isEmpty(list2); // true
CollectionUtils.isEmpty(list3); // false
// isNotEmpty
CollectionUtils.isNotEmpty(list); // false
CollectionUtils.isNotEmpty(list3); // true
// 对比直接调用的危险写法:
list.isEmpty(); // NullPointerException!!
集合运算
List<Integer> listA = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> listB = Arrays.asList(3, 4, 5, 6, 7);
// 交集(两个都有的)
Collection<Integer> intersection = CollectionUtils.intersection(listA, listB);
// [3, 4, 5]
// 并集(合并去重)
Collection<Integer> union = CollectionUtils.union(listA, listB);
// [1, 2, 3, 4, 5, 6, 7]
// 差集(A有,B没有)
Collection<Integer> subtract = CollectionUtils.subtract(listA, listB);
// [1, 2]
// 反向差集(B有,A没有)
Collection<Integer> subtract2 = CollectionUtils.subtract(listB, listA);
// [6, 7]
// 是否有交集
boolean isDisjoint = CollectionUtils.containsAny(listA, listB); // true
过滤 & 转换
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6));
// filter ------ 保留满足条件的元素(直接修改原list)
CollectionUtils.filter(list, n -> n % 2 == 0);
// list = [2, 4, 6]
// select ------ 返回新集合,不修改原list
Collection<Integer> evens = CollectionUtils.select(list, n -> n % 2 == 0);
// evens = [2, 4, 6],list不变
// selectRejected ------ 返回不满足条件的元素
Collection<Integer> odds = CollectionUtils.selectRejected(list, n -> n % 2 == 0);
// odds = [1, 3, 5]
// transform ------ 转换每个元素(直接修改原list)
CollectionUtils.transform(list, n -> n * 2);
// list = [2, 4, 6, 8, 10, 12]
// collect ------ 转换后返回新集合
Collection<String> strList = CollectionUtils.collect(list, n -> "num:" + n);
// ["num:1", "num:2", ...]
其他实用方法
// 判断是否是子集
List<Integer> sub = Arrays.asList(1, 2);
CollectionUtils.isSubCollection(sub, listA); // true
// 判断两个集合元素是否完全相同(忽略顺序)
CollectionUtils.isEqualCollection(listA, listB);
// 获取集合中第N个元素(支持各种集合类型)
CollectionUtils.get(list, 2); // 下标2的元素
// 统计满足条件的元素个数
int count = CollectionUtils.countMatches(list, n -> n > 3); // 2
// 判断集合中是否存在满足条件的元素
boolean exists = CollectionUtils.exists(list, n -> n > 3); // true
// 添加所有非null元素
CollectionUtils.addIgnoreNull(list, null); // null不会被加入
CollectionUtils.addIgnoreNull(list, 6); // 正常加入
三、CollectionUtils(Spring)
Spring项目里不需要额外引入,直接用。
import org.springframework.util.CollectionUtils;
List<String> list = null;
// 判空(同样null安全)
CollectionUtils.isEmpty(list); // true
CollectionUtils.isEmpty(map); // 也支持Map!Apache的不支持Map判空
// 把普通Map转成MultiValueMap(一个key对应多个value)
Map<String, List<String>> map = new HashMap<>();
map.put("hobby", Arrays.asList("篮球", "足球"));
MultiValueMap<String, String> multiMap = CollectionUtils.toMultiValueMap(map);
// 把数组转成ArrayList
String[] arr = {"a", "b", "c"};
List<String> fromArray = CollectionUtils.arrayToList(arr);
// 判断list中是否包含某个对象(用equals比较)
CollectionUtils.containsInstance(list, obj);
四、总结对比
| 方法 | Collections | Apache CollectionUtils | Spring CollectionUtils |
|---|---|---|---|
| 判空(null安全) | ❌ | ✅ | ✅ |
| Map判空 | ❌ | ❌ | ✅ |
| 排序 | ✅ | ❌ | ❌ |
| 交集并集差集 | ❌ | ✅ | ❌ |
| 过滤转换 | ❌ | ✅ | ❌ |
| 线程安全包装 | ✅ | ❌ | ❌ |
| 不可变集合 | ✅ | ❌ | ❌ |
| 需要额外依赖 | ❌ | ✅ | ✅(Spring项目自带) |
五、实际项目中的选择建议
// 场景1:判断集合是否为空 → Spring或Apache CollectionUtils
if (CollectionUtils.isNotEmpty(list)) { ... }
// 场景2:排序 → Collections
Collections.sort(list, Comparator.comparing(User::getAge));
// 场景3:集合求交集/并集/差集 → Apache CollectionUtils
CollectionUtils.intersection(listA, listB);
// 场景4:对外暴露的集合不想被修改 → Collections
return Collections.unmodifiableList(list);
// 场景5:多线程环境 → Collections或直接用ConcurrentHashMap
Collections.synchronizedList(list);