一、Collections 工具类
概念
java.util.Collections 是一个工具类,提供各种操作集合的静态方法(不可以被实例化,因为构造方法是私有的)
Collections和Collection的区别
| 方面 | Collection (接口) | Collections (工具类) |
|---|---|---|
| 类型 | 接口 (interface) | 工具类 (final class) |
| 包位置 | java.util.Collection | java.util.Collections |
| 主要作用 | 定义集合的基本操作规范 | 提供操作集合的实用静态方法 |
| 实例化 | 不能实例化,需要实现类 | 不能实例化(构造器私有) |
| 方法特点 | 抽象方法,需要子类实现 | 静态方法,直接调用 |
| 使用方式 | 多态,通过实现类使用 | 工具类,直接Collections.xxx() 调用 |
| 继承关系 | 集合框架的根接口之一 | 不继承任何接口,final class |
| 设计模式 | 接口模式,定义规范 | 工具类模式,提供实用方法 |
特点:
- 所有的方法都是静态的
- 主要操作List、Map、Set等集合
- 提供空集合和单元素集合
- 包含排序、搜索、同步包装、不可修改包装等方法
常用方法
1、排序和查找相关方法
1. sort() - 排序
java
// 自然排序(元素必须实现 Comparable)
List<Integer> numbers = new ArrayList<>(Arrays.asList(3, 1, 4, 1, 5));
Collections.sort(numbers); // [1, 1, 3, 4, 5]
// 自定义比较器排序
List<String> names = new ArrayList<>(Arrays.asList("John", "Alice", "Bob"));
Collections.sort(names, Comparator.reverseOrder()); // [John, Bob, Alice]
// 按字符串长度排序
Collections.sort(names, Comparator.comparingInt(String::length));
注意事项:需要配合Comparator使用
2. binarySearch() - 二分查找
java
List<Integer> sortedList = Arrays.asList(1, 3, 5, 7, 9);
// 前提:列表必须是有序的
int index = Collections.binarySearch(sortedList, 5); // 2
int notFound = Collections.binarySearch(sortedList, 4); // -3
// 自定义比较器的二分查找
List<String> words = Arrays.asList("apple", "banana", "cherry");
Collections.sort(words);
int idx = Collections.binarySearch(words, "banana"); // 1
注意事项:需要进行排序
3. reverse() - 反转
java
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
Collections.reverse(list); // [5, 4, 3, 2, 1]
4. shuffle() - 随机打乱
java
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
Collections.shuffle(list); // 随机顺序,如 [3, 1, 5, 2, 4]
// 使用指定随机源
Random random = new Random(42);
Collections.shuffle(list, random); // 可重现的随机顺序
5. swap() - 交换元素
java
List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C", "D"));
Collections.swap(list, 0, 3); // ["D", "B", "C", "A"]
注意事项:在原列表中进行操作不会创建出新的列表
6. rotate() - 旋转
java
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
Collections.rotate(list, 2); // [4, 5, 1, 2, 3] 向右旋转2位
Collections.rotate(list, -1); // [5, 1, 2, 3, 4] 向左旋转1位
2、最大最小值查找
7. max() / min() - 查找最大最小值
java
List<Integer> numbers = Arrays.asList(3, 1, 4, 1, 5);
// 自然顺序
Integer max = Collections.max(numbers); // 5
Integer min = Collections.min(numbers); // 1
// 自定义比较器
Integer maxByCustom = Collections.max(numbers,
(a, b) -> Integer.compare(a % 3, b % 3));
// 字符串最长/最短
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
String longest = Collections.max(names, Comparator.comparingInt(String::length)); // Charlie
String shortest = Collections.min(names, Comparator.comparingInt(String::length)); // Bob
注意事项:需要配合Comparator使用
3、频率和位置操作
8. frequency() - 统计频率
java
List<String> words = Arrays.asList("apple", "banana", "apple", "orange", "apple");
int freq = Collections.frequency(words, "apple"); // 3
int freq2 = Collections.frequency(words, "banana"); // 1
// 在 Set 中使用
Set<Integer> numbers = new HashSet<>(Arrays.asList(1, 2, 1, 3, 2));
int freq3 = Collections.frequency(numbers, 2); // 1(Set 中每个元素只出现一次)
9. indexOfSubList() / lastIndexOfSubList() - 查找子列表
java
List<Integer> source = Arrays.asList(1, 2, 3, 4, 1, 2, 3, 4);
List<Integer> target = Arrays.asList(2, 3);
int first = Collections.indexOfSubList(source, target); // 1
int last = Collections.lastIndexOfSubList(source, target); // 5
4、填充和替换操作
10. fill() - 填充
java
List<String> list = new ArrayList<>(Arrays.asList("a", "b", "c", "d"));
Collections.fill(list, "X"); // ["X", "X", "X", "X"]
// 注意:会替换所有元素
List<Integer> numbers = new ArrayList<>(Collections.nCopies(5, null));
Collections.fill(numbers, 0); // [0, 0, 0, 0, 0]
注意事项:常使用于初始化
11. replaceAll() - 替换所有
java
List<String> list = new ArrayList<>(Arrays.asList("foo", "bar", "foo", "test"));
boolean changed = Collections.replaceAll(list, "foo", "FOO"); // true
// 结果:["FOO", "bar", "FOO", "test"]
// 如果没有匹配项
boolean changed2 = Collections.replaceAll(list, "none", "NEW"); // false
注意事项:不会创建出来新数组
12. nCopies() - 创建多个副本
java
List<String> copies = Collections.nCopies(3, "Hello");
// ["Hello", "Hello", "Hello"]
// 注意:返回的是不可变列表
// 常见用法:初始化列表
List<String> list = new ArrayList<>(Collections.nCopies(10, ""));
5、不可修改和同步包装
13. unmodifiableXxx() - 不可修改视图
java
List<String> original = new ArrayList<>(Arrays.asList("A", "B", "C"));
List<String> unmodifiableList = Collections.unmodifiableList(original);
// 可以读取
String first = unmodifiableList.get(0); // "A"
// 不能修改
// unmodifiableList.add("D"); // UnsupportedOperationException
// unmodifiableList.set(0, "X"); // UnsupportedOperationException
// 原始列表修改会影响视图
original.add("D");
System.out.println(unmodifiableList.size()); // 4
14. synchronizedXxx() - 同步包装
java
// 创建线程安全的集合
List<String> syncList = Collections.synchronizedList(new ArrayList<>());
Map<String, String> syncMap = Collections.synchronizedMap(new HashMap<>());
Set<Integer> syncSet = Collections.synchronizedSet(new HashSet<>());
// 使用时需要注意
// 正确做法:迭代时需要手动同步
synchronized(syncList) {
Iterator<String> it = syncList.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
注意事项:常用,用于线程安全
15. checkedXxx() - 类型安全包装
java
// 创建类型安全的集合
List list = new ArrayList();
List<String> checkedList = Collections.checkedList(list, String.class);
// 现在添加错误类型会立即抛出异常
checkedList.add("Hello"); // OK
// checkedList.add(123); // ClassCastException(立即抛出)
// 适用于调试和防止类型污染
6、单元素和空集合
16. singleton() / singletonList() / singletonMap() - 单元素集合
java
Set<String> singleSet = Collections.singleton("unique");
List<Integer> singleList = Collections.singletonList(42);
Map<String, Integer> singleMap = Collections.singletonMap("key", 100);
// 这些集合都是不可修改的
// singleSet.add("another"); // UnsupportedOperationException
// 实用场景:从集合中移除特定元素
list.removeAll(Collections.singleton("removeMe"));
17. emptyXxx() - 空集合
java
// 安全的空集合
List<String> emptyList = Collections.emptyList();
Set<Integer> emptySet = Collections.emptySet();
Map<String, Object> emptyMap = Collections.emptyMap();
// 最佳实践:避免返回 null
public List<String> getNames() {
if (condition) {
return names;
}
return Collections.emptyList(); // 而不是 null
}
// 不可修改
// emptyList.add("item"); // UnsupportedOperationException
7、集合操作
18. addAll() - 批量添加
java
List<String> list = new ArrayList<>();
Collections.addAll(list, "A", "B", "C", "D"); // [A, B, C, D]
// 比 list.add("A"); list.add("B"); ... 更简洁
// 比 Arrays.asList("A", "B", "C", "D") 更高效(避免中间集合)
// 可以添加数组
String[] moreItems = {"E", "F"};
Collections.addAll(list, moreItems); // [A, B, C, D, E, F]
19. copy() - 复制列表
java
List<String> source = Arrays.asList("A", "B", "C");
List<String> dest = new ArrayList<>(Arrays.asList("1", "2", "3", "4", "5"));
// 目标列表必须至少和源列表一样长
Collections.copy(dest, source); // ["A", "B", "C", "4", "5"]
// 如果目标列表长度不够会抛出异常
// List<String> shortDest = new ArrayList<>(Arrays.asList("1", "2"));
// Collections.copy(shortDest, source); // IndexOutOfBoundsException
注意事项:浅拷贝
20. disjoint() - 检查是否无交集
java
List<Integer> list1 = Arrays.asList(1, 2, 3);
List<Integer> list2 = Arrays.asList(4, 5, 6);
List<Integer> list3 = Arrays.asList(3, 4, 5);
boolean noCommon1 = Collections.disjoint(list1, list2); // true
boolean noCommon2 = Collections.disjoint(list1, list3); // false(有共同元素3)
21. reverseOrder() - 获取逆序比较器
java
// 自然顺序的逆序
Comparator<Integer> reverseNatural = Collections.reverseOrder();
List<Integer> numbers = Arrays.asList(3, 1, 4, 1, 5);
numbers.sort(reverseNatural); // [5, 4, 3, 1, 1]
// 包装现有比较器
Comparator<String> byLength = Comparator.comparingInt(String::length);
Comparator<String> reverseByLength = Collections.reverseOrder(byLength);
二、Arrays工具类
Arrays 是 Java 中处理数组的核心工具类,提供了丰富的数组操作方法。
特点:
- 所有方法都是静态的
- 提供数组操作的各种工具方法
- 支持基本类型数组和对象数组
- 包含排序、搜索、比较、填充、转换等方法
常用方法
1、数组创建和初始化
1. asList() - 数组转列表
java
// 基本用法
String[] arr = {"Java", "Python", "C++"};
List<String> list = Arrays.asList(arr);
// 直接传入元素
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
// 注意:返回的是固定大小的列表
// list.add("New"); // 抛出 UnsupportedOperationException
// list.remove(0); // 抛出 UnsupportedOperationException
// 但可以修改元素
list.set(0, "JavaScript"); // 允许
**注意事项:**asList返回的是固定大小的列表,不可以添加和删除
2. copyOf() - 数组复制
java
int[] original = {1, 2, 3, 4, 5};
// 复制整个数组
int[] copy1 = Arrays.copyOf(original, original.length); // [1, 2, 3, 4, 5]
// 截断复制
int[] copy2 = Arrays.copyOf(original, 3); // [1, 2, 3]
// 扩展复制(多余位置填充默认值)
int[] copy3 = Arrays.copyOf(original, 7); // [1, 2, 3, 4, 5, 0, 0]
// 对象数组
String[] strArr = {"a", "b", "c"};
String[] strCopy = Arrays.copyOf(strArr, 5); // ["a", "b", "c", null, null]
注意事项:
- 对于基本类型数组:是深拷贝(完全独立的副本)
- 对于对象数组:是浅拷贝(只复制引用,不复制对象)
3. copyOfRange() - 范围复制
java
int[] arr = {1, 2, 3, 4, 5, 6, 7, 8};
// 复制指定范围 [from, to)
int[] range1 = Arrays.copyOfRange(arr, 2, 5); // [3, 4, 5]
// from 可以等于 to(空数组)
int[] range2 = Arrays.copyOfRange(arr, 3, 3); // []
// to 可以超过原数组长度
int[] range3 = Arrays.copyOfRange(arr, 5, 10); // [6, 7, 8, 0, 0]
注意事项:
- 对于基本类型数组:是深拷贝(完全独立的副本)
- 对于对象数组:是浅拷贝(只复制引用,不复制对象)
2、数组填充
4. fill() - 填充数组
java
// 基本类型数组
int[] intArr = new int[5];
Arrays.fill(intArr, 42); // [42, 42, 42, 42, 42]
boolean[] boolArr = new boolean[3];
Arrays.fill(boolArr, true); // [true, true, true]
// 对象数组
String[] strArr = new String[4];
Arrays.fill(strArr, "Hello"); // ["Hello", "Hello", "Hello", "Hello"]
// 填充指定范围 [fromIndex, toIndex)
int[] arr = new int[6];
Arrays.fill(arr, 1, 4, 9); // [0, 9, 9, 9, 0, 0]
// 多用途示例
int[] scores = new int[10];
Arrays.fill(scores, -1); // 初始化分数为-1
注意事项:多用于初始化
3、数组排序
5. sort() - 数组排序
java
// 基本类型排序(自然顺序)
int[] numbers = {5, 2, 9, 1, 7};
Arrays.sort(numbers); // [1, 2, 5, 7, 9]
// 对象数组排序(需要实现 Comparable)
String[] names = {"John", "Alice", "Bob"};
Arrays.sort(names); // ["Alice", "Bob", "John"]
// 部分排序
int[] arr = {9, 5, 3, 7, 1, 8};
Arrays.sort(arr, 2, 5); // 排序索引2到4:[9, 5, 1, 3, 7, 8]
// 自定义比较器(仅限对象数组)
String[] words = {"apple", "banana", "pear", "grape"};
Arrays.sort(words, Comparator.comparingInt(String::length));
// ["pear", "apple", "grape", "banana"]
// 降序排序
Integer[] nums = {5, 2, 9, 1, 7}; // 注意:必须用 Integer[] 而不是 int[]
Arrays.sort(nums, Comparator.reverseOrder()); // [9, 7, 5, 2, 1]
注意事项:需要配合Comparator使用
6. parallelSort() - 并行排序
java
// 大数据量时使用并行排序更高效
int[] largeArray = new int[100000];
Random random = new Random();
for (int i = 0; i < largeArray.length; i++) {
largeArray[i] = random.nextInt(1000000);
}
// 并行排序(适合多核处理器)
Arrays.parallelSort(largeArray);
// 也可以指定范围
Arrays.parallelSort(largeArray, 1000, 90000);
4、数组搜索
7. binarySearch() - 二分查找
java
// 前提:数组必须是有序的!
int[] sortedArr = {1, 3, 5, 7, 9, 11};
// 查找存在的元素
int index1 = Arrays.binarySearch(sortedArr, 5); // 2
int index2 = Arrays.binarySearch(sortedArr, 1); // 0
// 查找不存在的元素(返回插入点的负值-1)
int index3 = Arrays.binarySearch(sortedArr, 4); // -3(插入点为2,返回-2-1)
int index4 = Arrays.binarySearch(sortedArr, 12); // -7(插入点为6,返回-6-1)
// 在指定范围内查找
int index5 = Arrays.binarySearch(sortedArr, 1, 4, 7); // 在索引1-3查找:3
// 对象数组二分查找(需要比较器)
String[] sortedNames = {"Alice", "Bob", "Charlie", "David"};
int idx = Arrays.binarySearch(sortedNames, "Charlie"); // 2
// 自定义比较器
String[] words = {"apple", "banana", "cherry", "date"};
Arrays.sort(words, Comparator.comparingInt(String::length));
int pos = Arrays.binarySearch(words, "fig",
Comparator.comparingInt(String::length)); // 查找长度为3的单词
注意事项:需要进行排序,才可以使用二分查找,要不没有作用
5、数组比较
8. equals() - 数组相等比较
java
// 基本类型数组比较
int[] arr1 = {1, 2, 3};
int[] arr2 = {1, 2, 3};
int[] arr3 = {1, 2, 4};
boolean eq1 = Arrays.equals(arr1, arr2); // true
boolean eq2 = Arrays.equals(arr1, arr3); // false
// 对象数组比较(使用元素的 equals 方法)
String[] str1 = {"a", "b", "c"};
String[] str2 = {"a", "b", "c"};
String[] str3 = {"a", "b", "C"}; // 注意大小写
boolean seq1 = Arrays.equals(str1, str2); // true
boolean seq2 = Arrays.equals(str1, str3); // false
// 指定范围比较
int[] a1 = {1, 2, 3, 4, 5};
int[] a2 = {9, 2, 3, 4, 0};
boolean rangeEq = Arrays.equals(a1, 1, 4, a2, 1, 4); // true
注意事项:使用equals,比较逻辑和引用数据类型中自己定义的一样
9. deepEquals() - 深度比较(多维数组)
java
// 一维数组可以用 equals,多维数组必须用 deepEquals
int[][] matrix1 = {{1, 2}, {3, 4}};
int[][] matrix2 = {{1, 2}, {3, 4}};
int[][] matrix3 = {{1, 2}, {3, 5}};
boolean deepEq1 = Arrays.deepEquals(matrix1, matrix2); // true
boolean deepEq2 = Arrays.deepEquals(matrix1, matrix3); // false
// 对象数组的深度比较
String[][] names1 = {{"Alice", "Bob"}, {"Charlie", "David"}};
String[][] names2 = {{"Alice", "Bob"}, {"Charlie", "David"}};
boolean namesEq = Arrays.deepEquals(names1, names2); // true
注意事项:多维度数组
6、数组转字符串
10. toString() - 数组转字符串
java
// 基本类型数组
int[] intArr = {1, 2, 3};
String intStr = Arrays.toString(intArr); // "[1, 2, 3]"
// 对象数组
String[] strArr = {"Java", "Python"};
String strStr = Arrays.toString(strArr); // "[Java, Python]"
// 空数组
int[] empty = {};
String emptyStr = Arrays.toString(empty); // "[]"
// 调试输出
System.out.println("Array: " + Arrays.toString(arr));
11. deepToString() - 深度转字符串
java
// 多维数组必须用 deepToString
int[][] matrix = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
String matrixStr = Arrays.deepToString(matrix);
// "[[1, 2, 3], [4, 5, 6], [7, 8, 9]]"
// 对比 toString 的错误输出
System.out.println(Arrays.toString(matrix));
// 输出类似 "[[I@1b6d3586, [I@4554617c, [I@74a14482]"
// 对象多维数组
String[][] names = {{"Alice", "Bob"}, {"Charlie", "David"}};
String namesStr = Arrays.deepToString(names);
// "[[Alice, Bob], [Charlie, David]]"
注意事项:多维数组必须用 deepToString
7、哈希码和流操作
12. hashCode() / deepHashCode() - 哈希码
java
// 一维数组哈希码
int[] arr = {1, 2, 3};
int hash1 = Arrays.hashCode(arr);
// 多维数组哈希码
int[][] matrix = {{1, 2}, {3, 4}};
int deepHash = Arrays.deepHashCode(matrix);
// 用于 HashMap 等集合
Map<int[], String> map = new HashMap<>();
map.put(arr, "value");
13. stream() - 数组转流
java
// Java 8+ 将数组转为 Stream
int[] numbers = {1, 2, 3, 4, 5};
// IntStream
int sum = Arrays.stream(numbers).sum(); // 15
long count = Arrays.stream(numbers).count(); // 5
double avg = Arrays.stream(numbers).average().orElse(0); // 3.0
// 过滤和转换
int[] evenNumbers = Arrays.stream(numbers)
.filter(n -> n % 2 == 0)
.toArray(); // [2, 4]
// 对象数组
String[] names = {"Alice", "Bob", "Charlie"};
List<String> upperNames = Arrays.stream(names)
.map(String::toUpperCase)
.collect(Collectors.toList()); // [ALICE, BOB, CHARLIE]
// 范围流
int[] partialSum = Arrays.stream(numbers, 1, 4).toArray(); // [2, 3, 4]
8、高级和并行操作
14. parallelPrefix() - 并行前缀和
java
// 计算前缀和(累加和)
int[] arr = {1, 2, 3, 4, 5};
Arrays.parallelPrefix(arr, (a, b) -> a + b);
// 结果:[1, 3, 6, 10, 15]
// 计算前缀积
int[] numbers = {1, 2, 3, 4, 5};
Arrays.parallelPrefix(numbers, (a, b) -> a * b);
// 结果:[1, 2, 6, 24, 120]
// 字符串连接
String[] words = {"Hello", " ", "World", "!"};
Arrays.parallelPrefix(words, (a, b) -> a + b);
// 结果:["Hello", "Hello ", "Hello World", "Hello World!"]
15. parallelSetAll() - 并行设置所有元素
java
// 并行初始化数组
int[] squares = new int[10];
Arrays.parallelSetAll(squares, i -> i * i);
// 结果:[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
// 生成随机数
double[] randoms = new double[100];
Random random = new Random();
Arrays.parallelSetAll(randoms, i -> random.nextDouble());
// 生成序列
String[] sequence = new String[5];
Arrays.parallelSetAll(sequence, i -> "Item-" + (i + 1));
// 结果:["Item-1", "Item-2", "Item-3", "Item-4", "Item-5"]
16. setAll() - 设置所有元素
java
// 顺序初始化(比 parallelSetAll 更适合小数组)
int[] arr = new int[5];
Arrays.setAll(arr, i -> i * 10);
// 结果:[0, 10, 20, 30, 40]
// 生成斐波那契数列
int[] fibonacci = new int[10];
Arrays.setAll(fibonacci, i -> {
if (i < 2) return 1;
return fibonacci[i-1] + fibonacci[i-2];
});
// 结果:[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]