JDK1.8 之后 Comparator 接口新增了哪些默认方法如何使用?

文章导读
JDK 1.8 为 Comparator 接口引入了默认方法,最常用的是 reversed() 和 thenComparing() 系列,适合在不创建新类的情况下实现链式排序逻辑。注意这是 JDK 1.8 版本引入的特性,而非 1.8 之后的版本。
📋 目录
  1. 新增默认方法列表
  2. 完整代码示例
  3. 空值处理最佳实践
  4. 怎么验证是否生效
  5. 常见坑
A A

JDK 1.8 为 Comparator 接口引入了默认方法,最常用的是 reversed() 和 thenComparing() 系列,适合在不创建新类的情况下实现链式排序逻辑。注意这是 JDK 1.8 版本引入的特性,而非 1.8 之后的版本。

先说结论:默认方法让排序规则组合更灵活,主要解决多条件排序和逆序需求,无需额外工具类。

  • 适合:集合排序需要动态组合规则的场景,如先按年龄再按姓名排序。
  • 核心方法:reversed() 用于反转顺序,thenComparing() 及其变体用于追加条件。
  • 建议:配合 Lambda 表达式使用,代码更简洁,但必须注意空指针风险,建议配合 nullsFirst/nullsLast 使用。

新增默认方法列表

除了常见的 reversed() 和 thenComparing(Comparator),JDK 1.8 还针对基本类型提供了优化方法,避免装箱开销:

  • reversed():返回一个逆序比较器。
  • thenComparing(Comparator):追加另一个比较器。
  • thenComparingInt(ToIntFunction):追加 int 类型键的比较,性能更好。
  • thenComparingLong(ToLongFunction):追加 long 类型键的比较。
  • thenComparingDouble(ToDoubleFunction):追加 double 类型键的比较。

完整代码示例

以下是一个完整可运行的 Java 类示例,展示了多条件排序及基本类型优化方法的使用:

JDK1.8 之后 Comparator 接口新增了哪些默认方法如何使用?
import java.util.*;
import java.util.Comparator;

public class ComparatorDemo {
    static class Person {
        String name;
        int age;
        long salary;
        public Person(String name, int age, long salary) {
            this.name = name; this.age = age; this.salary = salary;
        }
        public String toString() { return name + "-" + age + "-" + salary; }
        public int getAge() { return age; }
        public long getSalary() { return salary; }
    }

    public static void main(String[] args) {
        List<Person> list = Arrays.asList(
            new Person("Alice", 25, 10000),
            new Person("Bob", 25, 8000),
            new Person("Charlie", 30, 12000)
        );

        // 多条件排序:先按年龄升序,年龄相同按薪水降序
        list.sort(Comparator.comparingInt(Person::getAge)
            .thenComparing(Comparator.comparingLong(Person::getSalary).reversed()));

        list.forEach(System.out::println);
    }
}

空值处理最佳实践

默认方法本身不处理 null 值。如果集合元素或比较字段可能为 null,需配合静态方法 nullsFirst 或 nullsLast 使用,否则可能抛出 NullPointerException。

// 安全排序:null 值排在前面,再按年龄排序
list.sort(Comparator.nullsFirst(Comparator.comparingInt(Person::getAge)));

// 字段可能为 null 的情况
list.sort(Comparator.comparing(Person::getName, Comparator.nullsLast(Comparator.naturalOrder())));

怎么验证是否生效

1. 运行测试:编写一个 main 方法,创建包含重复字段值的对象列表。

2. 打印结果:排序后遍历打印列表,观察顺序是否符合预期(如降序或第二条件生效)。

JDK1.8 之后 Comparator 接口新增了哪些默认方法如何使用?

3. 检查日志:如果有自定义比较逻辑,可在比较方法中打日志,确认 thenComparing 是否在第一个条件相等时被调用。

常见坑

1. 空指针异常:默认方法本身不处理 null 值。如果集合元素或比较字段可能为 null,需配合静态方法 nullsFirst 或 nullsLast 使用,否则可能抛出 NullPointerException。

JDK1.8 之后 Comparator 接口新增了哪些默认方法如何使用?

2. 静态与默认混淆:comparing、naturalOrder 等是静态方法,需要通过类名调用;reversed、thenComparing 是默认方法,需要通过实例调用。混淆会导致编译错误。

3. 基本类型支持:Comparator 主要针对对象。如果是 int[] 等基本类型数组,不能直接使用 List.sort,需先装箱或使用 Arrays.sort 的特定重载。

4. 版本兼容性:确保项目 JDK 版本为 1.8 或更高,否则无法识别 default 关键字和相应方法。