在 Java 开发中,数组、集合和对象是我们每天都会打交道的核心元素。为了简化这些元素的操作,JDK 提供了三个超实用的工具类:Arrays
(数组操作)、Collections
(集合操作)、Objects
(对象工具)。它们就像 "瑞士军刀",封装了大量常用功能,能帮我们少写几百行代码。今天就带大家深入剖析这三个工具类的核心用法、底层逻辑和避坑指南,配上直观图解,让你一次掌握!
一、Arrays:数组操作的 "全能助手"
数组是 Java 中最基础的数据结构,但原生数组的操作(排序、查找、复制等)并不方便。java.util.Arrays
类专门为数组提供了一系列静态方法,让数组操作变得简单高效。
1. 核心功能:排序、查找、填充、复制
(1)排序:sort()
------ 让数组有序化
Arrays.sort()
支持对各种类型的数组进行排序,底层根据数组类型选择不同算法(基本类型用双轴快速排序,对象类型用 TimSort)。
java
// 基本类型数组排序
int[] nums = {3, 1, 4, 1, 5};
Arrays.sort(nums); // 排序后:[1, 1, 3, 4, 5]
// 对象数组排序(需实现Comparable或传入Comparator)
String[] strs = {"apple", "banana", "cherry"};
Arrays.sort(strs); // 按自然顺序排序:[apple, banana, cherry]
// 指定范围排序(从索引1到4,左闭右开)
int[] arr = {5, 3, 8, 2, 7};
Arrays.sort(arr, 1, 4); // 排序后:[5, 2, 3, 8, 7]
(2)查找:binarySearch()
------ 快速定位元素
二分查找必须在已排序的数组中使用,返回元素索引(未找到则返回负数)。
java
int[] nums = {1, 3, 5, 7, 9};
int index = Arrays.binarySearch(nums, 5); // 返回2(找到)
int notFound = Arrays.binarySearch(nums, 4); // 返回-3(未找到,插入点为2)
(3)填充:fill()
------ 批量设置元素值
快速将数组的指定范围填充为同一个值,适合初始化数组。
java
int[] arr = new int[5];
Arrays.fill(arr, 10); // 全部填充10:[10, 10, 10, 10, 10]
// 填充指定范围
Arrays.fill(arr, 1, 3, 20); // 索引1-2填充20:[10, 20, 20, 10, 10]
(4)复制:copyOf()
与arraycopy()
------ 数组克隆与截取
copyOf()
:从原数组开头复制指定长度(新数组长度可大于原数组,多余部分补默认值)。arraycopy()
:从原数组指定位置复制到目标数组(更灵活,需手动创建目标数组)。
java
int[] original = {1, 2, 3, 4, 5};
// copyOf:复制前3个元素
int[] copy1 = Arrays.copyOf(original, 3); // [1, 2, 3]
// arraycopy:从原数组索引1复制2个元素到目标数组索引0
int[] copy2 = new int[2];
System.arraycopy(original, 1, copy2, 0, 2); // copy2:[2, 3]
2. 实用功能:数组转集合与内容比较
(1)asList()
:数组转 List 集合
将数组转换为List
,但注意:返回的是Arrays.ArrayList
(Arrays 的内部类),不支持添加 / 删除元素 (会抛UnsupportedOperationException
)。
java
String[] strs = {"a", "b", "c"};
List<String> list = Arrays.asList(strs);
list.set(0, "x"); // 支持修改元素
// list.add("d"); // 报错:UnsupportedOperationException
坑点:如果传入基本类型数组 ,
asList()
会将整个数组当作一个元素(因为泛型不支持基本类型)。例如int[]
转 List 会得到List<int[]>
,而非List<Integer>
。解决办法:用包装类数组(Integer[]
)。
(2)equals()
与deepEquals()
:数组内容比较
equals()
:比较一维数组的元素是否完全相同(基本类型比较值,对象比较引用)。deepEquals()
:用于多维数组比较(递归比较嵌套数组的内容)。
java
int[] a = {1, 2};
int[] b = {1, 2};
System.out.println(Arrays.equals(a, b)); // true(内容相同)
int[][] c = {{1, 2}, {3, 4}};
int[][] d = {{1, 2}, {3, 4}};
System.out.println(Arrays.equals(c, d)); // false(二维数组用equals比较引用)
System.out.println(Arrays.deepEquals(c, d)); // true(深层比较内容)
3. Arrays 功能图解

二、Collections:集合操作的 "瑞士军刀"
java.util.Collections
是针对集合框架(List、Set、Map)的工具类,提供了排序、查找、同步控制、不可变集合等实用功能,与Arrays
遥相呼应。
1. 核心功能:排序、查找、反转
(1)排序:sort()
------List 排序神器
与Arrays.sort()
类似,但专门用于List
集合,支持自然排序和自定义比较器。
java
List<Integer> list = new ArrayList<>(Arrays.asList(3, 1, 4));
Collections.sort(list); // 自然排序:[1, 3, 4]
// 自定义比较器(降序)
Collections.sort(list, (a, b) -> b - a); // [4, 3, 1]
(2)查找:binarySearch()
与indexOfSubList()
binarySearch()
:在已排序的 List 中查找元素(同 Arrays,依赖排序)。indexOfSubList()
:查找子列表在父列表中的起始索引(未找到返回 - 1)。
java
List<String> list = Arrays.asList("a", "b", "c", "d");
int index = Collections.binarySearch(list, "c"); // 返回2
List<String> subList = Arrays.asList("b", "c");
int subIndex = Collections.indexOfSubList(list, subList); // 返回1(子列表从索引1开始)
(3)反转与打乱:reverse()
与shuffle()
reverse()
:反转 List 中元素的顺序。shuffle()
:随机打乱元素顺序(适合洗牌、随机抽样场景)。
java
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4));
Collections.reverse(list); // [4, 3, 2, 1]
Collections.shuffle(list); // 随机顺序,如[2, 4, 1, 3]
2. 进阶功能:同步集合与不可变集合
(1)同步集合:synchronizedXxx()
------ 线程安全的集合
为非线程安全的集合(如 ArrayList、HashMap)生成线程安全的版本(通过包装器实现,底层用synchronized
加锁)。
java
// 创建线程安全的List
List<String> syncList = Collections.synchronizedList(new ArrayList<>());
// 创建线程安全的Map
Map<String, Integer> syncMap = Collections.synchronizedMap(new HashMap<>());
注意:同步集合是 "粗粒度" 锁,性能较低,高并发场景建议用
java.util.concurrent
包下的并发集合(如 ConcurrentHashMap)。
(2)不可变集合:unmodifiableXxx()
------ 只读集合
创建不可修改的集合(禁止添加、删除、修改元素),适合保护数据不被篡改。
java
List<String> original = new ArrayList<>(Arrays.asList("a", "b"));
List<String> unmodifiable = Collections.unmodifiableList(original);
// unmodifiable.add("c"); // 报错:UnsupportedOperationException
original.add("c"); // 原集合修改,不可变集合也会同步变化(注意!)
更彻底的不可变集合:用
List.of()
(Java 9+),原集合修改不影响不可变集合,且性能更好。
3. 其他实用方法
fill(list, obj)
:用指定对象填充 List(覆盖所有元素)。max(collection)
/min(collection)
:获取集合中的最大 / 小元素(依赖排序)。frequency(collection, obj)
:统计元素在集合中出现的次数。swap(list, i, j)
:交换 List 中两个索引的元素。
4. Collections 功能图解

三、Objects:对象操作的 "安全卫士"
java.util.Objects
(Java 7+)是处理对象的工具类,封装了对象的比较、空值判断、哈希计算等常用操作,尤其擅长避免NullPointerException
(空指针异常)。
1. 核心功能:空值处理与对象比较
(1)空值判断:isNull()
与nonNull()
简化null
判断,比obj == null
更直观。
java
String str = null;
System.out.println(Objects.isNull(str)); // true(是否为null)
System.out.println(Objects.nonNull(str)); // false(是否不为null)
(2)非空校验:requireNonNull()
------ 快速失败
在方法入参校验时使用,若对象为null
则立即抛出NullPointerException
,避免后续逻辑出错。
java
public void process(String str) {
// 校验参数非空,为空则抛异常
Objects.requireNonNull(str, "参数str不能为null");
// 后续逻辑...
}
(3)对象比较:equals()
与deepEquals()
equals(a, b)
:安全比较两个对象是否相等(避免a.equals(b)
中a
为null
的问题)。deepEquals(a, b)
:深度比较(适合数组或对象引用的嵌套结构)。
java
String a = "hello";
String b = "hello";
String c = null;
// 安全比较,避免空指针
System.out.println(Objects.equals(a, b)); // true
System.out.println(Objects.equals(a, c)); // false(c为null时不报错)
// 深度比较数组
int[] arr1 = {1, 2};
int[] arr2 = {1, 2};
System.out.println(Objects.equals(arr1, arr2)); // false(数组引用不同)
System.out.println(Objects.deepEquals(arr1, arr2)); // true(内容相同)
2. 其他实用方法
-
hash(obj...)
:计算多个对象的哈希值(比手动计算更方便,支持可变参数)。javaint hash = Objects.hash("a", 123, true); // 组合哈希值
-
toString(obj)
:安全获取对象的字符串表示(对象为null
时返回 "null",而非抛异常)。javaString str = null; System.out.println(Objects.toString(str)); // "null" System.out.println(Objects.toString(str, "默认值")); // "默认值"(自定义null时的返回值)
-
compare(a, b, comparator)
:使用比较器比较两个对象(支持null
,默认null
小于非 null)。
3. Objects 功能图解

四、总结:三大工具类的核心价值
工具类 | 核心场景 | 最常用方法 | 避坑要点 |
---|---|---|---|
Arrays |
数组排序、查找、复制 | sort() 、binarySearch() 、copyOf() |
asList() 返回的 List 不可修改;基本类型数组转集合需用包装类 |
Collections |
集合排序、同步、不可变 | sort() 、synchronizedList() 、reverse() |
同步集合性能低,高并发用并发集合;不可变集合依赖原集合 |
Objects |
对象空值处理、比较 | isNull() 、equals() 、requireNonNull() |
equals() 与deepEquals() 的区别;toString() 的 null 安全 |
这三个工具类的设计思想是 "封装共性操作,减少重复代码"。熟练掌握它们,不仅能提升开发效率,还能避免手动实现时的潜在 bug(如空指针、排序算法错误)。记住:JDK 自带的工具类往往经过了充分优化和测试,优先使用它们,而不是重复造轮子!
最后,建议大家多翻 JDK 源码(比如Arrays.sort()
的实现、Objects.equals()
的空值处理逻辑),深入理解底层原理,才能真正做到灵活运用。
版权声明:本博客内容为原创,转载请保留原文链接及作者信息。