一、Collections 工具类
专门操作 Collection 体系(List、Set)和 Map 的工具类,核心功能涵盖排序、查找、填充、同步化、不可变封装等。
1. 核心功能分类 & 常用方法
| 功能分类 |
方法签名(核心) |
说明 |
| 排序(List) |
sort(List<T> list) |
自然排序:要求元素实现 Comparable 接口,升序排列 |
|
sort(List<T> list, Comparator<? super T> c) |
定制排序:通过 Comparator 自定义排序规则 |
|
reverse(List<?> list) |
反转列表元素顺序 |
|
shuffle(List<?> list) |
随机打乱列表(洗牌),常用于随机排序 |
|
swap(List<?> list, int i, int j) |
交换列表中指定索引的两个元素 |
|
rotate(List<?> list, int distance) |
旋转列表:distance 正数右移,负数左移(如 distance=1,最后一个元素移到首位) |
| 查找/替换 |
binarySearch(List<T> list, T key) |
二分查找:前提是列表已排序(自然排序),找到返回索引,否则返回 -(插入点)-1 |
|
binarySearch(List<T> list, T key, Comparator<? super T> c) |
带比较器的二分查找 |
|
max(Collection<T> coll) / min(Collection<T> coll) |
找集合的最大/最小值(自然排序) |
|
max(Collection<T> coll, Comparator<? super T> c) |
定制规则找最大/最小值 |
|
fill(List<? super T> list, T obj) |
用指定元素填充整个列表(覆盖所有元素) |
|
replaceAll(List<T> list, T oldVal, T newVal) |
替换列表中所有旧元素为新元素 |
|
frequency(Collection<?> c, Object o) |
统计元素在集合中出现的次数 |
| 同步化包装 |
synchronizedList(List<T> list) |
返回线程安全的 List(底层加锁,性能较低) |
|
synchronizedSet(Set<T> s) / synchronizedMap(Map<K,V> m) |
返回线程安全的 Set/Map |
| 不可变封装 |
emptyList() / emptySet() / emptyMap() |
返回空的不可变集合(复用单例,节省内存) |
|
singletonList(T o) / singletonSet(T o) / singletonMap(K k, V v) |
返回包含单个元素的不可变集合 |
|
unmodifiableList(List<? extends T> list) |
将现有集合包装为不可变集合(修改会抛 UnsupportedOperationException) |
| 其他工具 |
addAll(Collection<? super T> c, T... elements) |
批量添加元素到集合 |
|
disjoint(Collection<?> c1, Collection<?> c2) |
判断两个集合是否无交集(无则返回 true) |
|
copy(List<? super T> dest, List<? extends T> src) |
复制 src 到 dest:要求 dest 容量 ≥ src 大小,否则抛 IndexOutOfBoundsException |
|
nCopies(int n, T o) |
返回包含 n 个相同元素的不可变 List |
2. 关键示例
(1)排序(自然 + 定制)
java
复制代码
List<Integer> list = new ArrayList<>(Arrays.asList(3, 1, 2));
// 自然排序(升序)
Collections.sort(list); // [1,2,3]
// 定制排序(降序)
Collections.sort(list, (a, b) -> b - a); // [3,2,1]
// 反转
Collections.reverse(list); // [1,2,3]
// 洗牌
Collections.shuffle(list);
(2)不可变集合
java
复制代码
// 空不可变List
List<String> emptyList = Collections.emptyList();
// 单元素不可变List
List<String> singletonList = Collections.singletonList("test");
// 包装现有List为不可变
List<String> mutableList = new ArrayList<>();
mutableList.add("a");
List<String> unmodifiableList = Collections.unmodifiableList(mutableList);
// 不可变集合修改会抛异常
// unmodifiableList.add("b"); // UnsupportedOperationException
(3)同步化集合
java
复制代码
// 线程安全的List
List<String> syncList = Collections.synchronizedList(new ArrayList<>());
// 迭代时需手动加锁(否则可能抛ConcurrentModificationException)
synchronized (syncList) {
for (String s : syncList) {
System.out.println(s);
}
}
3. 注意事项
- 不可变集合的"假不可变" :
unmodifiableXXX 仅包装原集合,若原集合修改,包装后的不可变集合会同步变化(因为是引用传递)。
- copy 方法的容量要求 :
Collections.copy(dest, src) 要求 dest.size() ≥ src.size(),而非仅容量(需提前初始化 dest 大小)。
- 同步化集合性能 :底层通过
synchronized 加锁,性能低于 java.util.concurrent 包下的并发集合(如 CopyOnWriteArrayList)。
二、Arrays 工具类
专门操作数组(基本类型数组、对象数组)的工具类,核心功能涵盖排序、查找、填充、复制、数组转集合、比较/哈希等。
1. 核心功能分类 & 常用方法
| 功能分类 |
方法签名(核心) |
说明 |
| 排序 |
sort(int[] a) / sort(Object[] a) |
基本类型数组升序;对象数组要求元素实现 Comparable |
|
sort(Object[] a, Comparator<? super T> c) |
对象数组定制排序(仅支持对象数组,不支持基本类型) |
|
parallelSort(int[] a) |
并行排序:大数据量(百万级)更高效(Java 8+) |
| 查找 |
binarySearch(int[] a, int key) / binarySearch(Object[] a, Object key) |
二分查找:数组需先排序,找到返回索引,否则返回 -(插入点)-1 |
|
binarySearch(Object[] a, Object key, Comparator<? super T> c) |
带比较器的二分查找(仅对象数组) |
| 填充 |
fill(int[] a, int val) / fill(Object[] a, T val) |
填充整个数组 |
|
fill(int[] a, int fromIndex, int toIndex, int val) |
填充指定范围(左闭右开) |
| 复制 |
copyOf(int[] original, int newLength) |
复制数组:新长度,不足补默认值(基本类型 0,对象 null) |
|
copyOfRange(int[] original, int from, int to) |
复制指定范围(左闭右开) |
| 数组转集合 |
asList(T... a) |
将数组转为 List(注意:返回的是 Arrays.ArrayList,非 java.util.ArrayList) |
| 比较/哈希 |
equals(int[] a, int[] a2) |
比较两个数组是否相等(长度+对应元素) |
|
deepEquals(Object[] a1, Object[] a2) |
深度比较:用于多维数组 |
|
toString(int[] a) |
返回数组的字符串表示(如 [1,2,3]) |
|
deepToString(Object[] a) |
多维数组的字符串表示 |
| 其他 |
stream(int[] a) |
转为 Stream(Java 8+) |
|
mismatch(int[] a, int[] a2) |
查找第一个不匹配的索引,无则返回 -1(Java 9+) |
2. 关键示例
(1)排序 & 二分查找
java
复制代码
int[] arr = {3, 1, 2};
// 排序
Arrays.sort(arr); // [1,2,3]
// 二分查找
int index = Arrays.binarySearch(arr, 2); // 返回1
int notFoundIndex = Arrays.binarySearch(arr, 4); // 返回-4(-(3)-1)
// 对象数组定制排序
String[] strArr = {"b", "a", "c"};
Arrays.sort(strArr, (s1, s2) -> s2.compareTo(s1)); // [c,b,a]
(2)数组复制
java
复制代码
int[] original = {1,2,3};
// 复制为新长度(不足补0)
int[] copy1 = Arrays.copyOf(original, 5); // [1,2,3,0,0]
// 复制指定范围
int[] copy2 = Arrays.copyOfRange(original, 0, 2); // [1,2]
// 底层依赖的System.arraycopy(更高效)
int[] dest = new int[3];
System.arraycopy(original, 0, dest, 0, original.length);
(3)数组转集合(重点避坑)
java
复制代码
// 正确:包装类数组转List
Integer[] intArr = {1,2,3};
List<Integer> list1 = Arrays.asList(intArr);
// 错误:基本类型数组转List(会被当成单个元素)
int[] primitiveArr = {1,2,3};
List<int[]> list2 = Arrays.asList(primitiveArr); // 类型是List<int[]>,而非List<Integer>
// 注意:Arrays.asList返回的List不可增删(固定大小)
// list1.add(4); // UnsupportedOperationException
// 若需可变List,需二次包装
List<Integer> mutableList = new ArrayList<>(Arrays.asList(intArr));
mutableList.add(4); // 正常
(4)多维数组比较 & 字符串表示
java
复制代码
// 多维数组
int[][] arr1 = {{1,2}, {3,4}};
int[][] arr2 = {{1,2}, {3,4}};
int[][] arr3 = {{1,2}, {3,5}};
// 深度比较
System.out.println(Arrays.deepEquals(arr1, arr2)); // true
System.out.println(Arrays.deepEquals(arr1, arr3)); // false
// 深度字符串表示
System.out.println(Arrays.deepToString(arr1)); // [[1,2],[3,4]]
3. 注意事项
- Arrays.asList 坑点 :
- 基本类型数组转换会被视为单个元素(需用包装类数组);
- 返回的
Arrays.ArrayList 是静态内部类,无 add/remove 方法(仅实现 set),修改会抛异常;
- 二分查找前提:必须先排序,否则结果无意义;
- parallelSort 适用场景:仅大数据量(百万级以上)有性能优势,小数据量反而因线程开销更慢。
三、Collections & Arrays 对比
| 维度 |
Collections |
Arrays |
| 操作对象 |
List、Set、Map(集合) |
基本类型数组、对象数组 |
| 核心功能 |
排序(仅List)、查找、填充、同步化、不可变封装 |
排序(所有数组)、查找、填充、复制、数组转集合、比较/哈希 |
| 线程安全 |
提供同步化包装方法 |
无 |
| 不可变封装 |
提供 emptyXXX/singletonXXX/unmodifiableXXX |
仅 asList 返回固定大小 List |
| 集合转数组 |
无(集合自身有 toArray() 方法) |
无(提供数组转集合) |
四、常见避坑总结
- 不可变集合修改 :
Collections.unmodifiableXXX 和 Arrays.asList 返回的集合,调用 add/remove 均会抛 UnsupportedOperationException;
- Collections.copy 容量 :目标 List 需提前初始化大小(
size()),而非仅指定容量;
- Arrays.asList 基本类型 :避免直接传入
int[]/long[] 等基本类型数组,需转为 Integer[]/Long[];
- 二分查找前置条件 :无论是
Collections.binarySearch 还是 Arrays.binarySearch,必须先对目标排序;
- 同步化集合迭代 :
Collections.synchronizedXXX 返回的集合,迭代时需手动加锁,否则可能出现并发修改异常。