一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

Java Stream排序实战:Sorted方法和自定义比较器

时间:2026-06-24 08:38:03 编辑:袖梨 来源:一聚教程网

Java Stream的sorted()提供自然排序与自定义排序两种方式:无参版要求元素实现Comparable,有参版通过Comparator精确控制逻辑,支持comparing、thenComparing链式多级排序及nullsFirst/nullsLast空值处理。

Java Stream 的 sorted() 方法是处理集合排序最常用、最简洁的工具之一。它不依赖外部循环或手动算法,而是通过声明式方式表达排序意图。关键在于理解两种调用形式的适用场景,以及如何用 Comparator 精准控制排序逻辑。

自然排序与自定义排序的区别

无参的 sorted() 要求元素类型实现 Comparable 接口,例如 IntegerString 默认按数值或字典序升序排列:

  • 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) -> { /* 复杂分支判断 */ },但优先考虑组合静态方法以提升可读性

不复杂但容易忽略

热门栏目