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());
相关推荐
西凉的悲伤12 小时前
Spring Boot 条件装配注解详解
java·springboot·1024程序员节·条件装配
木井巳12 小时前
【动态规划: 路径问题】不同路径
java·算法·leetcode·动态规划
打工仔折腾 AI12 小时前
AI Agent 工程化实战(二):5 分钟跑通 Deep Agent 并逐层拆解底层链路
java·数据库·人工智能·后端·python·langchain·ai agent 实战
秋名RG13 小时前
(二)存储、CPU 与指令执行——程序为什么快,又为什么慢
java·开发语言
BeiGuTing_code13 小时前
Java泛型与Object
java·开发语言
惊讶的猫13 小时前
Tika文档解析
java
HEJOO913 小时前
Java 类加载过程详解:从加载到初始化的完整链路
java·开发语言·firefox
科学熊13 小时前
Java 分布式理论与高并发编程
java·开发语言·分布式
砚底藏山河13 小时前
python量化实操:回测数据缓存与重放
java·python·金融·1024程序员节
学长毕设13 小时前
基于springboot的农资管理系统-附源码
java·spring boot·后端