最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
Java Stream排序实战:Sorted方法和自定义比较器
时间:2026-06-24 08:38:03 编辑:袖梨 来源:一聚教程网
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 快速按字段排序
对单个属性排序,推荐使用 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 是核心
真实业务中常需“先按部门升序,再按薪资降序,最后按入职时间升序”。这靠链式调用 thenComparing() 实现:
-
Comparator.comparing(User::getDept)—— 主排序键 -
.thenComparing(User::getSalary, Comparator.reverseOrder())—— 次级键,降序 -
.thenComparing(User::getHireDate)—— 第三级,自然升序
所有 thenComparing 调用都支持传入比较器,因此可自由组合升/降序,无需嵌套或手写 compare() 方法。
处理 null 值和复杂逻辑
实际数据常含 null 字段。Java 提供了专门的空值处理方法:
-
nullsFirst()和nullsLast()包裹任意比较器,例如nullsLast(Comparator.comparing(User::getEmail)) - 对两个可能为
null的字符串安全比较:Comparator.nullsLast(String::compareToIgnoreCase) - 需要自定义逻辑(如按状态分组再排序)时,仍可用 Lambda:
(u1, u2) -> { /* 复杂分支判断 */ },但优先考虑组合静态方法以提升可读性
不复杂但容易忽略