Collections.sort()适用于ArrayList等支持随机访问的List,升序直接调用,降序或自定义需传Comparator;Stream.sorted()适合不可变集合或链式操作;TreeSet/TreeMap天然有序但去重且不存null;自定义Comparator须防溢出、空指针和顺序错误。

用 Collections.sort() 对 ArrayList 排序最直接
如果集合是 ArrayList 且元素实现了 Comparable(比如 String、Integer),直接调用 Collections.sort(list) 就行,原地升序排列。
常见错误是传入 LinkedList 或 HashSet 后发现报错 —— Collections.sort() 要求传入的是 List,且底层需支持随机访问才高效;对 LinkedList 虽不报错但性能差(O(n²) 比较 + O(n) 链表寻址)。
- 升序:
Collections.sort(names); // names 是 ArrayList
- 降序:
Collections.sort(numbers, Collections.reverseOrder());
- 自定义排序:
Collections.sort(people, (a, b) -> a.getAge() - b.getAge());
对不可变集合或 Stream 场景优先用 Stream.sorted()
当你处理的是 Arrays.asList() 返回的不可变列表、或想链式操作(比如先 filter 再排序),用 Stream 更安全自然。它不修改原集合,返回新 List。
注意:stream().sorted() 默认要求元素可比较;若元素类型没实现 Comparable,必须显式传 Comparator,否则运行时报 ClassCastException。
立即学习“Java免费学习笔记(深入)”;
- 基础用法:
List
sorted = list.stream().sorted().collect(Collectors.toList()); - 按字段排序:
List
sorted = users.stream().sorted(Comparator.comparing(User::getName)).collect(Collectors.toList()); - 空值安全:用
Comparator.nullsLast()避免NullPointerException:.sorted(Comparator.nullsLast(Comparator.comparing(User::getEmail)))
TreeSet 和 TreeMap 天然有序,但有严格限制
如果你的业务需要「插入即自动维持顺序」,且不介意去重(TreeSet)或键值结构(TreeMap),可以用它们替代手动排序。但要注意:
- 构造时必须提供
Comparator,或元素必须实现Comparable;否则添加元素时抛ClassCastException - 不能存
null(除非Comparator显式允许) -
TreeSet不保留插入顺序,也不保证线程安全 - 底层是红黑树,增删查都是 O(log n),比
ArrayList.sort()的 O(n log n) 单次排序开销高,适合频繁增删+查序场景
示例:
Setset = new TreeSet<>(Comparator.reverseOrder()); // 降序 TreeSet
自定义 Comparator 时别踩这些坑
手写 Comparator 最容易出错的地方不是逻辑,而是整数溢出和 null 处理。
- 避免直接用
a - b比较int字段:当a = Integer.MAX_VALUE、b = -1时结果为负,排序翻车。改用Integer.compare(a, b) - 字符串比较别用
==或str1.compareTo(str2) > 0判空后逻辑,应统一用Objects.equals()+Comparator.nullsLast() - 复合排序别链式写错顺序:先按年龄升序、再按姓名降序,要写成
Comparator.comparing(User::getAge).thenComparing(User::getName, Comparator.reverseOrder())
,而不是反过来
排序本身不难,难的是在 null、重复、并发、性能边界下保持稳定 —— 多数问题其实出在没看清集合类型和 comparator 合约。










