第32篇:Java常用工具类(Objects、Collections、Arrays深入)
📌 系列导航 :《Java 100 天进阶之路》完整目录 |
⬅️ 上一篇:第31篇:Java数组详解 |
➡️ 下一篇:第33篇:Java中的static关键字详解
一、核心知识点
java.util.Objects类:null 安全的方法(equals、hashCode、toString、requireNonNull、isNull等)java.util.Collections类:集合的操作(排序、混排、不可变集合、同步包装器)java.util.Arrays类:数组的操作(排序、二分查找、填充、拷贝、转 List)java.util.Comparable与Comparator:对象的排序
二、通俗讲解(1分钟开心学)
1. Objects 工具类
Java 7 引入,专门处理可能为 null 的对象,避免手动写 if (obj != null)。例如 Objects.equals(a, b) 会在 a 和 b 都为 null 时返回 true,其中一个 null 时返回 false,比 a.equals(b) 安全。
2. Collections 工具类
操作 Collection 和 Map 的静态方法:
sort(List<T>):排序(要求元素实现Comparable)reverse(List):反转shuffle(List):随机打乱unmodifiableList(List):返回只读视图synchronizedList(List):返回线程安全的包装
3. Arrays 工具类
操作数组的静态方法:
sort()、binarySearch()、fill()、copyOf()、equals()asList():将数组转成List(注意返回的是固定大小的Arrays.ArrayList)
4. 排序比较器
- 对象自然排序:实现
Comparable<T>接口,重写compareTo - 定制排序:实现
Comparator<T>接口,重写compare
生活类比 :
Objects就像安全扶手,防止你在 null 上摔跤。Collections和Arrays就像瑞士军刀,给集合和数组提供各种常用工具。
三、实操代码案例 + 场景说明
场景:对员工列表进行多种排序(按姓名、按工资),并确保集合不可修改。
java
import java.util.*;
import java.util.stream.Collectors;
class Employee implements Comparable<Employee> {
private String name;
private double salary;
public Employee(String name, double salary) {
this.name = name;
this.salary = salary;
}
public String getName() { return name; }
public double getSalary() { return salary; }
// 自然排序:按姓名
@Override
public int compareTo(Employee o) {
return this.name.compareTo(o.name);
}
@Override
public String toString() {
return String.format("%s(%.0f)", name, salary);
}
// 静态工厂方法用于创建 Comparator
public static Comparator<Employee> byName = Comparator.comparing(Employee::getName);
public static Comparator<Employee> bySalary = Comparator.comparingDouble(Employee::getSalary);
}
public class UtilsDemo {
public static void main(String[] args) {
// 1. Objects 工具类
String s1 = null;
String s2 = "hello";
System.out.println(Objects.equals(s1, s2)); // false
System.out.println(Objects.hashCode(s1)); // 0
System.out.println(Objects.toString(s1, "默认")); // 默认
Objects.requireNonNull(s2, "s2 不能为 null"); // 不抛异常
// Objects.requireNonNull(s1, "s1 不能为 null"); // 会抛 NPE
// 2. Collections 与 Arrays
List<Integer> list = new ArrayList<>(Arrays.asList(3, 1, 4, 1, 5));
Collections.sort(list);
System.out.println(list); // [1,1,3,4,5]
Collections.reverse(list);
System.out.println(list); // [5,4,3,1,1]
Collections.shuffle(list);
System.out.println("随机:" + list);
// 不可变集合
List<Integer> unmod = Collections.unmodifiableList(list);
// unmod.add(10); // 抛 UnsupportedOperationException
// 3. 数组工具
int[] arr = {5,2,8,1};
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
int index = Arrays.binarySearch(arr, 8);
System.out.println("8的位置:" + index);
int[] copy = Arrays.copyOf(arr, 10);
System.out.println("拷贝并扩容:" + Arrays.toString(copy));
// 4. 员工排序
List<Employee> employees = Arrays.asList(
new Employee("Bob", 5000),
new Employee("Alice", 7000),
new Employee("Charlie", 6000)
);
// 按姓名排序
employees.sort(Employee.byName);
System.out.println("按姓名:" + employees);
// 按工资排序
employees.sort(Employee.bySalary);
System.out.println("按工资:" + employees);
// 链式排序:先按工资,再按姓名
employees.sort(Employee.bySalary.thenComparing(Employee.byName));
}
}
四、避坑要点
| 错误/误区 | 后果 | 正确做法 |
|---|---|---|
Arrays.asList(arr) 返回的 List 调用 add/remove |
UnsupportedOperationException |
用 new ArrayList<>(Arrays.asList(arr)) |
修改 Collections.unmodifiableXxx 返回的集合 |
抛异常 | 不要尝试修改,或先拷贝再修改 |
Objects.equals(a, b) 与 a.equals(b) 混淆 |
前者 null 安全,后者可能 NPE | 不确定是否为 null 时用 Objects.equals |
自定义 Comparator 时未处理 null |
可能 NPE | 使用 Comparator.nullsFirst 或 nullsLast |
五、面试高频考点
Q1:Objects.equals(a, b) 和 a.equals(b) 的区别?
Objects.equals是 null 安全的,两个都为 null 返回 true,一个为 null 返回 false,否则调用a.equals(b)。后者在 a 为 null 时抛 NPE。
Q2:Collections.sort(list) 和 list.sort(null) 的区别?
功能相同,
list.sort(null)是List接口的默认方法(Java 8 引入),可以直接被集合调用。Collections.sort是旧 API,内部调用了list.sort。
Q3:如何将数组转换成可变的 ArrayList?
new ArrayList<>(Arrays.asList(arr))
六、练习题
- 填空 :使用
Objects.requireNonNull替代手动 null 检查。 - 排序:对一组字符串按长度排序,长度相同再按字典序。
- 动手 :实现一个
Comparator<Person>,先按年龄降序,再按姓名升序。
📊 你的学习进度
- 当前:第32篇 / 共44篇 · 第五阶段:工具类、异常最佳实践、序列化(第32~35篇)
- ✅ 已完成:第1~31篇
- 📖 正在学:第32篇
- ⏳ 待学习:第33~44篇
👉 📚 完整目录 & 学习指南 | 🔥 订阅本专栏,不错过每一篇
💡 本专栏每篇都包含:避坑表 + 面试高频考点 + 练习题。每天30分钟,100天拿offer!
👉 下一篇文章预告
《第33篇:Java中的static关键字详解》
内容简介:静态变量/方法/代码块,内存位置(方法区),静态导入,静态方法的重写问题。
💡 学完这篇,你将彻底掌握static的语义,面试再问静态成员轻松回答。
📌 《Java 100 天进阶之路 | 从入门到上岗就业》 每天一篇,建议收藏 + 关注 ,一起100天拿offer!
👉 点击关注我,更新后第一时间收到推送!