Collections.sort()对ArrayList自然排序需元素实现Comparable且非null,否则抛异常;自定义类须实现compareTo();不可用于不可变集合;自定义排序用Comparator;Stream.sorted()生成新列表不改原List;LinkedList排序性能差于ArrayList。

用 Collections.sort() 对 ArrayList 做自然排序
如果 List 里是 String、Integer 这类实现了 Comparable 的类型,直接调用 Collections.sort(list) 就行。它会按元素自身的 compareTo() 逻辑升序排列,原地修改,不返回新列表。
常见错误:对 null 元素调用会抛 NullPointerException;对未实现 Comparable 的自定义对象调用会报 ClassCastException。
- 确保所有元素非
null,或提前过滤:list.removeIf(Objects::isNull) - 若元素是自定义类,必须让该类实现
Comparable接口并重写compareTo() - 该方法只适用于
ArrayList、LinkedList等支持随机访问或可遍历的List实现,不适用于不可变集合(如Arrays.asList()返回的固定大小列表,排序可能抛UnsupportedOperationException)
用 Comparator 实现自定义排序逻辑
当需要按多个字段、逆序、忽略大小写,或元素本身没实现 Comparable 时,传入一个 Comparator 是最常用方式。Java 8+ 推荐用 lambda 或方法引用写法,简洁且不易出错。
示例:按 User 对象的年龄降序,年龄相同时按姓名升序:
立即学习“Java免费学习笔记(深入)”;
Collections.sort(users, (a, b) -> {
int ageDiff = Integer.compare(b.getAge(), a.getAge()); // 降序
if (ageDiff != 0) return ageDiff;
return a.getName().compareTo(b.getName()); // 升序
});- 避免在
compare()中直接用a.age - b.age,整数溢出会导致错误结果;应使用Integer.compare(a, b) - 字符串比较别用
==或String.compareTo()忽略空值;优先用Comparator.nullsLast(Comparator.naturalOrder()) -
Comparator可复用:定义为静态常量(如User.AGE_DESC),避免每次新建对象影响 GC
用 Stream.sorted() 获取新排序列表(不改原 List)
如果不想修改原始 List,而是想生成一个排好序的新集合,用 stream().sorted().collect(Collectors.toList()) 更安全直观。它返回的是新 ArrayList,原始列表完全不受影响。
注意点:
- 性能略低于
Collections.sort()(多一次遍历 + 新建对象),大数据量时需权衡 - 若原始
List是不可变的(如Arrays.asList()或List.of()),这是唯一可行方式,否则会抛异常 - 链式调用中,
sorted()必须在filter()、map()后置——排序依赖完整数据流,提前截断会丢失排序依据
对 LinkedList 排序要留意性能差异
Collections.sort() 内部对 RandomAccess 子类(如 ArrayList)用的是优化过的 Timsort,时间复杂度接近 O(n log n);但对 LinkedList,它会先转成数组再排序,最后写回链表——多两次 O(n) 遍历,实际开销更大。
- 如果频繁排序且用的是
LinkedList,考虑换成ArrayList,除非你明确依赖链表的插入/删除特性 - 不要为了“看起来像链表”而用
LinkedList存数据;99% 场景下ArrayList更合适 - 若必须用
LinkedList且排序频繁,可手动转成数组排序后再构建新链表,但通常得不偿失
排序真正麻烦的不是语法,而是 null 处理、不可变集合兼容性、以及误以为 LinkedList 和 ArrayList 在排序时表现一致。这些地方一不留神就进坑。









