可通过comparator.comparing()链式调用实现多字段排序:先按grade升序,相同时按score升序,再相同时按name字典升序;需降序则用reversed();手动实现或lambda适用于空值处理等复杂场景。

可以通过 Collections.sort() 配合自定义 Comparator 实现多字段排序,核心是按优先级依次比较各字段,前一个字段相等时才继续比下一个。
使用 Comparator.comparing() 链式调用(推荐,Java 8+)
这是最简洁、可读性最强的方式,利用 thenComparing() 方法逐层追加排序条件:
Collections.sort(list, Comparator.comparing(Student::getGrade)
.thenComparing(Student::getScore)
.thenComparing(Student::getName));
说明:
- 先按
grade升序; -
grade相同时,按score升序; -
grade和score都相同时,再按name字典升序。
如需降序,对某字段调用 reversed(),例如:comparing(Student::getScore).reversed()。
重写 compare() 手动实现多字段逻辑
适合需要精细控制(如空值处理、复杂比较规则)的场景:
Collections.sort(list, new Comparator<student>() {
@Override
public int compare(Student s1, Student s2) {
// 第一维度:grade
int gradeDiff = Integer.compare(s1.getGrade(), s2.getGrade());
if (gradeDiff != 0) return gradeDiff;
// 第二维度:score(降序)
int scoreDiff = Integer.compare(s2.getScore(), s1.getScore()); // 注意顺序翻转
if (scoreDiff != 0) return scoreDiff;
// 第三维度:name(忽略大小写)
return s1.getName().compareToIgnoreCase(s2.getName());
}
});
</student>
使用 Lambda 表达式简化匿名类
语法更紧凑,逻辑与手动实现一致:
Collections.sort(list, (s1, s2) -> {
int c1 = Integer.compare(s1.getGrade(), s2.getGrade());
if (c1 != 0) return c1;
int c2 = Integer.compare(s2.getScore(), s1.getScore()); // score 降序
if (c2 != 0) return c2;
return s1.getName().compareToIgnoreCase(s2.getName());
});
注意事项和常见技巧
关键细节不能忽略:
-
空值安全:若字段可能为
null,避免直接调用方法。可用Comparator.nullsFirst()或nullsLast()包装,例如:comparing(Student::getNickname, nullsLast(String::compareTo)); -
原始类型包装:对
int/double等用Integer.compare()、Double.compare(),避免自动拆箱导致NullPointerException; -
不可变性:排序会直接修改原列表,如需保留原始顺序,先调用
new ArrayList(originalList)复制一份; -
替代方案:Java 8 起更推荐用
list.sort(comparator)(ArrayList自带),语义更清晰,且无需导入Collections。










