Java中对对象数组排序需实现Comparable接口或传入Comparator,推荐用Comparator.comparing等方法处理null、类型及多字段组合,注意避免溢出和违反比较契约。

Java 中用 Arrays.sort 对对象数组按字段排序,核心在于提供明确的比较逻辑——要么让类实现 Comparable 接口定义自然顺序,要么传入 Comparator 实现定制化比较。两者选其一即可,关键在比较规则写得准、不越界、不忽略 null。
用 Comparator 按单个字段排序(推荐)
这是最灵活、最常用的方式,无需修改原类,适合临时排序或多种排序策略共存的场景。以 User 类为例:
// 假设 User 有 name(String) 和 age(int) 字段
按年龄升序:
立即学习“Java免费学习笔记(深入)”;
- 用
Comparator.comparingInt(User::getAge),自动处理 int 类型比较 - 若 age 可能为 null,改用
Comparator.comparing(User::getAge, Comparator.nullsLast(Comparator.naturalOrder())) - 降序则链式调用
.reversed(),如comparingInt(User::getAge).reversed()
按多个字段组合排序(如先按部门,再按薪资)
利用 thenComparing 链式构建优先级顺序,清晰表达“主序→次序”逻辑:
-
Comparator.comparing(User::getDept).thenComparing(User::getSalary):部门升序,同部门内薪资升序 - 支持混合类型和方向:
comparing(User::getDept).thenComparingInt(User::getSalary).reversed()表示先按部门升序,再按薪资降序 - 任意字段为 null 时,建议统一用
nullsFirst或nullsLast包裹,避免NullPointerException
实现 Comparable 接口(适合固定自然顺序)
当该类“理应”有一个公认的默认排序方式(如 Date 按时间、String 按字典序),可让类自身实现 Comparable:
- 在
User中重写compareTo,例如按 id 升序:return Integer.compare(this.id, other.id); - 注意判空:
if (other == null) return 1;或抛ClassCastException更严谨 - 实现后直接调用
Arrays.sort(users)即可,无需额外参数
避坑要点:null、类型、稳定性
Arrays.sort 对对象数组使用的是**双轴快排(JDK 7+)或 TimSort(针对小数组或部分有序)**,它稳定(相等元素相对位置不变),但前提是你的比较器满足“自反性、对称性、传递性”。常见错误:
- 直接用
a.field - b.field算 int 差值 → 可能整数溢出,务必用Integer.compare(a, b) - 字符串比较用
a.name.equals(b.name)返回布尔值 → 错!必须返回 int,应改用a.name.compareTo(b.name)或Comparator.nullsLast(Comparator.naturalOrder()) - 在 lambda 中抛异常或返回随机值 → 破坏排序契约,结果不可预测


















