Java8 Comparator接口 和 List Steam 排序使用案例

在Java中,Comparator接口主要用于实现自定义排序逻辑,适用于未实现Comparable接口或需要覆盖默认比较规则的场景。以下是核心使用方法和注意事项:

一、基础用法

  1. 匿名内部类实现

    传统方式通过匿名内部类重写compare()方法,例如对整数降序排序:

    java 复制代码
    List<Integer> list = Arrays.asList(3, 1, 2); 
    list.sort(new Comparator<Integer>() { 
                @Override public int compare(Integer o1, Integer o2) {
                        // 降序 
                         return o2 - o1; 
                    } } );

    此方式在Java 8之前常见。

  2. Lambda表达式简化

    Java 8后可用Lambda替代匿名类,代码更简洁:

    java 复制代码
    list.sort((o1, o2) -> o2 - o1);

    或使用方法引用:

    java 复制代码
    list.sort(Comparator.reverseOrder());

    适用于简单排序场景。

二、高级特性

  1. 多条件排序

    使用thenComparing()实现多级排序,例如先按年龄升序,再按姓名降序:

    java 复制代码
    List<Person> people = ...; 
    people.sort( Comparator.comparing(Person::getAge) 
                          .thenComparing(Comparator.comparing(Person::getName)
                          .reversed() ) );

    支持链式调用,灵活组合排序规则。

  2. 处理null值

    需显式处理null避免NullPointerException,例如将null排在末尾:

    java 复制代码
    list.sort((a, b) -> {
                     if (a == null) return 1;
                     if (b == null) return -1; 
                    return a.compareTo(b);
                 });

    注意违反自反性会导致Comparison method violates its general contract错误。

三、Comparator与Comparable对比

维度 Comparator Comparable
实现位置 独立类或匿名类 目标类内部实现
排序规则 支持多种自定义规则 仅提供单一自然排序
侵入性 无侵入,不影响原有类 需修改类结构
典型应用场景 第三方类排序、多规则排序 类自身有明确排序逻辑(如String)

优先使用Comparator实现灵活排序,尤其是需要动态调整规则时。

四、常见问题

  1. 整数溢出风险
    避免直接返回o1 - o2,应使用

    java 复制代码
    Integer.compare(o1, o2)。
  2. JDK8增强方法

    • Comparator.naturalOrder():自然排序
    • Comparator.nullsFirst():将null置于开头
    • Comparator.comparingInt():避免装箱开销68。

通过合理应用Comparator,可高效实现复杂排序需求,同时保持代码可维护性。

Java 8的 Stream API 提供了强大的List排序功能,主要通过sorted()方法实现,支持自然排序、自定义排序以及多条件组合排序。以下是核心用法总结:

1. 基础排序

  • 自然排序(升序) ‌:直接调用sorted()方法,元素需实现Comparable接口

    java 复制代码
    list.stream().sorted().collect(Collectors.toList()); 
  • 降序排序 ‌:通过Comparator.reverseOrder()reversed()方法

    java 复制代码
    list.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
     // 或 
    list.stream().sorted(Comparator.comparing(Person::getAge).reversed())
                 .collect(Collectors.toList());

2. 自定义排序

  • 单字段排序 ‌:使用Comparator.comparing()指定字段

    java 复制代码
    list.stream().sorted(Comparator.comparing(Student::getScore))
            .collect(Collectors.toList());
  • 多字段排序 ‌:通过thenComparing()链式调用

    java 复制代码
    list.stream() .sorted(Comparator.comparing(Student::getAge)   
            .thenComparing(Student::getName)) .collect(Collectors.toList());

3. 空值处理

  • 空值优先/后置 ‌:使用Comparator.nullsFirst()Comparator.nullsLast()

    java 复制代码
    list.stream() .sorted(Comparator.comparing(Student::getAge,           
                               Comparator.nullsFirst(Integer::compareTo))) 
                .collect(Collectors.toList());

4. 性能提示

  • sorted()操作对大型流可能较昂贵,若数据已排序可跳过此操作2
  • 复杂排序建议预编译Comparator以减少重复计算9

完整示例:

java 复制代码
List<Student> students = Arrays.asList( 
        new Student("Alice", 25), 
        new Student("Bob", 20) );

List<Student> sorted = students.stream() 
                    .sorted(Comparator.comparing(Student::getAge).reversed()) 
                    .collect(Collectors.toList());
相关推荐
缺点内向20 小时前
Java:创建、读取或更新 Excel 文档
java·excel
带刺的坐椅21 小时前
Solon v3.4.7, v3.5.6, v3.6.1 发布(国产优秀应用开发框架)
java·spring·solon
四谎真好看1 天前
Java 黑马程序员学习笔记(进阶篇18)
java·笔记·学习·学习笔记
桦说编程1 天前
深入解析CompletableFuture源码实现(2)———双源输入
java·后端·源码
java_t_t1 天前
ZIP工具类
java·zip
lang201509281 天前
Spring Boot优雅关闭全解析
java·spring boot·后端
pengzhuofan1 天前
第10章 Maven
java·maven
百锦再1 天前
Vue Scoped样式混淆问题详解与解决方案
java·前端·javascript·数据库·vue.js·学习·.net
刘一说1 天前
Spring Boot 启动慢?启动过程深度解析与优化策略
java·spring boot·后端
壹佰大多1 天前
【spring如何扫描一个路径下被注解修饰的类】
java·后端·spring