Collections.sort是Java中原地排序List的常用工具,单参数依赖Comparable接口实现自然排序,双参数通过Comparator支持多字段、null安全等定制化排序,需注意溢出、null处理及列表可修改性。

Collections.sort 是 Java 中最直接、最常用的列表排序工具,它不创建新集合,而是原地修改 List。用得好,代码清晰;用得随意,容易出空指针或溢出问题。关键不在“能不能排”,而在“怎么排得稳、准、可维护”。
单参数:依赖自然顺序,适合基础类型
当 List 元素本身实现了 Comparable 接口(如 Integer、String、LocalDateTime),直接传入 list 即可升序排列:
- Integer、Double 等包装类默认按数值升序
- String 默认按字典序升序(区分大小写)
- 自定义类若想支持单参数调用,必须实现 Comparable 并重写 compareTo() ——但不推荐在业务实体中硬编码排序逻辑,耦合度高、难复用
双参数:用 Comparator 定制规则,主力场景
绝大多数真实业务都需要多字段、升降混合、null 安全的排序,这时必须传入 Comparator 实现。推荐两种主流写法:
-
Lambda 表达式(日常开发首选):简洁直观,适合一次性排序逻辑
Collections.sort(users, (u1, u2) -> {
int ageCmp = Integer.compare(u1.getAge(), u2.getAge());
if (ageCmp != 0) return ageCmp;
int scoreCmp = Double.compare(u2.getScore(), u1.getScore()); // 降序:u2 在前
if (scoreCmp != 0) return scoreCmp;
return Objects.compare(u1.getName(), u2.getName(), String::compareTo);
}); -
Comparator 静态链式构建(模块化/测试友好):把排序策略抽成常量或工具方法,便于复用和单元验证
public static final ComparatorBY_AGE_SCORE_NAME =
Comparator.comparing(User::getAge)
.thenComparing(User::getScore, Comparator.nullsLast(Comparator.reverseOrder()))
.thenComparing(User::getName, Comparator.nullsFirst(String::compareTo));
Collections.sort(users, BY_AGE_SCORE_NAME);
关键细节不能跳过
看似简单的一行 sort,实际藏着几个高频踩坑点:
立即学习“Java免费学习笔记(深入)”;
- 基本类型比较别用减法:Integer.compare(a, b) 替代 a - b,避免整型溢出(如 Integer.MAX_VALUE - (-1))
- null 值必须显式处理:String 或 Double 字段可能为 null,用 Comparator.nullsFirst() 或 Comparator.nullsLast() 包裹比较器,否则抛 NullPointerException
- 字符串忽略大小写:用 String.CASE_INSENSITIVE_ORDER.compare(s1, s2),而非 toLowerCase().compareTo()
- List 必须可修改:Arrays.asList() 返回的是固定大小列表,调用 sort 会抛 UnsupportedOperationException;需 new ArrayList(list) 包装后再排
替代方案提醒:List.sort() 和 Stream.sorted()
Collections.sort(list, cmp) 和 list.sort(cmp) 功能一致,后者是 Java 8+ List 接口新增方法,语义更明确;Stream.sorted() 则返回新 List,不改原数据——三者选哪个,取决于你是否需要保留原始顺序、是否在流式处理链中。但 Collections.sort 仍是多数传统业务代码中最稳定、最易调试的选择。


















