在Java里如何对集合进行排序_Java集合排序方案说明

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

Collections.sort()ArrayList 排序最直接

如果集合是 ArrayList 且元素实现了 Comparable(比如 StringInteger),直接调用 Collections.sort(list) 就行,原地升序排列。

常见错误是传入 LinkedListHashSet 后发现报错 —— 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

  • 基础用法:
    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)))

TreeSetTreeMap 天然有序,但有严格限制

如果你的业务需要「插入即自动维持顺序」,且不介意去重(TreeSet)或键值结构(TreeMap),可以用它们替代手动排序。但要注意:

  • 构造时必须提供 Comparator,或元素必须实现 Comparable;否则添加元素时抛 ClassCastException
  • 不能存 null(除非 Comparator 显式允许)
  • TreeSet 不保留插入顺序,也不保证线程安全
  • 底层是红黑树,增删查都是 O(log n),比 ArrayList.sort() 的 O(n log n) 单次排序开销高,适合频繁增删+查序场景

示例:

Set set = new TreeSet<>(Comparator.reverseOrder()); // 降序 TreeSet

自定义 Comparator 时别踩这些坑

手写 Comparator 最容易出错的地方不是逻辑,而是整数溢出和 null 处理。

  • 避免直接用 a - b 比较 int 字段:当 a = Integer.MAX_VALUEb = -1 时结果为负,排序翻车。改用 Integer.compare(a, b)
  • 字符串比较别用 ==str1.compareTo(str2) > 0 判空后逻辑,应统一用 Objects.equals() + Comparator.nullsLast()
  • 复合排序别链式写错顺序:先按年龄升序、再按姓名降序,要写成
    Comparator.comparing(User::getAge).thenComparing(User::getName, Comparator.reverseOrder())
    ,而不是反过来

排序本身不难,难的是在 null、重复、并发

、性能边界下保持稳定 —— 多数问题其实出在没看清集合类型和 comparator 合约。