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);