Java Stream的sorted()提供自然排序与自定义排序两种方式:无参版要求元素实现Comparable,有参版通过Comparator精确控制逻辑,支持comparing、thenComparing链式多级排序及nullsFirst/nullsLast空值处理。
Java Stream 的 sorted() 方法是处理集合排序最常用、最简洁的工具之一。它不依赖外部循环或手动算法,而是通过声明式方式表达排序意图。关键在于理解两种调用形式的适用场景,以及如何用 Comparator 精准控制排序逻辑。
无参的 sorted() 要求元素类型实现 Comparable 接口,例如 Integer、String 默认按数值或字典序升序排列:
List<Integer> nums = List.of(3, 1, 4); nums.stream().sorted().toList() → [1, 3, 4]
List<String> words = List.of("banana", "apple"); words.stream().sorted().toList() → ["apple", "banana"]
但自定义对象(如 User)若未实现 Comparable,直接调用无参 sorted() 会抛出 ClassCastException。此时必须使用带 Comparator 的重载版本。
对单个属性排序,推荐使用 Comparator.comparing(),它自动处理 null 安全性(除非显式指定),且语义清晰:
立即学习“Java免费学习笔记(深入)”;
Comparator.comparing(User::getAge)
Comparator.comparing(User::getName, Comparator.comparing(String::length).reversed())
Comparator.comparing(String::toLowerCase) 或直接用 String.CASE_INSENSITIVE_ORDER
注意:若 getAge() 可能返回 null,应改用 comparing(…, nullsLast(Integer::compareTo)) 避免空指针。
真实业务中常需“先按部门升序,再按薪资降序,最后按入职时间升序”。这靠链式调用 thenComparing() 实现:
Comparator.comparing(User::getDept) —— 主排序键.thenComparing(User::getSalary, Comparator.reverseOrder()) —— 次级键,降序.thenComparing(User::getHireDate) —— 第三级,自然升序所有 thenComparing 调用都支持传入比较器,因此可自由组合升/降序,无需嵌套或手写 compare() 方法。
实际数据常含 null 字段。Java 提供了专门的空值处理方法:
nullsFirst() 和 nullsLast() 包裹任意比较器,例如 nullsLast(Comparator.comparing(User::getEmail))
null 的字符串安全比较:Comparator.nullsLast(String::compareToIgnoreCase)
(u1, u2) -> { /* 复杂分支判断 */ },但优先考虑组合静态方法以提升可读性不复杂但容易忽略