168. Java Lambda 表达式 - 专用比较器

文章目录

  • [168. Java Lambda 表达式 - 专用比较器](#168. Java Lambda 表达式 - 专用比较器)
      • [✅ 解决方案:专用版本的 `comparing` 和 `thenComparing`](#✅ 解决方案:专用版本的 comparing 和 thenComparing)
        • [🧱 `Comparator.comparingXXX()`](#🧱 Comparator.comparingXXX())
        • [🔗 `thenComparingXXX()`](#🔗 thenComparingXXX())
      • [🎯 示例:比较学生成绩和年龄](#🎯 示例:比较学生成绩和年龄)
        • [🧪 正常写法(存在装箱):](#🧪 正常写法(存在装箱):)
        • [🚀 专用写法(无装箱):](#🚀 专用写法(无装箱):)
        • [🔗 链接更多字段(如年龄):](#🔗 链接更多字段(如年龄):)
      • [🧠 思维导图式理解](#🧠 思维导图式理解)
      • [🧩 小贴士](#🧩 小贴士)
      • [💬 举个练习题](#💬 举个练习题)

168. Java Lambda 表达式 - 专用比较器

当我们使用 Comparator.comparing() 或 thenComparing() 来构建比较器时,如果涉及的是 基本数据类型(如 int、long、double) ,JDK 通常会将它们进行 装箱 和 拆箱。

🤔 装箱/拆箱的问题:

  • int → Integer
  • double → Double
  • long → Long

虽然语法上没有问题,但它会引入性能开销,特别是在大规模数据排序时,这个开销是可以优化掉的!


✅ 解决方案:专用版本的 comparing 和 thenComparing

Java 提供了针对原始类型的 专用版本,避免自动装箱,提升性能:

🧱 Comparator.comparingXXX()
方法名 描述
comparingInt(ToIntFunction<T> keyExtractor) 比较 int 类型的字段
comparingLong(ToLongFunction<T> keyExtractor) 比较 long 类型的字段
comparingDouble(ToDoubleFunction<T> keyExtractor) 比较 double 类型的字段
🔗 thenComparingXXX()
方法名 描述
thenComparingInt(ToIntFunction<T> keyExtractor) 后续比较 int 字段
thenComparingLong(ToLongFunction<T> keyExtractor) 后续比较 long 字段
thenComparingDouble(ToDoubleFunction<T> keyExtractor) 后续比较 double 字段

🎯 示例:比较学生成绩和年龄

假设我们有如下 Student 类:

java 复制代码
class Student {
    public Student(String name, int score, int age) {
        this.name = name;
        this.score = score;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", score=" + score +
                ", age=" + age +
                '}';
    }

    private String name;
    private int score;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
🧪 正常写法(存在装箱):
java 复制代码
Comparator<Student> byScore =
    Comparator.comparing(student -> student.getScore()); // 装箱:int -> Integer
🚀 专用写法(无装箱):
java 复制代码
Comparator<Student> byScore =
    Comparator.comparingInt(Student::getScore);
🔗 链接更多字段(如年龄):
java 复制代码
Comparator<Student> byScoreThenAge =
    Comparator.comparingInt(Student::getScore)
              .thenComparingInt(Student::getAge);

🧠 思维导图式理解

java 复制代码
Comparator.comparingInt(...)       // 优化 int 字段比较
    ↳ .thenComparingInt(...)       // 链接另一个 int 比较字段
    ↳ .thenComparing(...)          // 仍可比较非原始类型字段(如 name)

🧩 小贴士

  • 如果你处理的是性能敏感的代码(如排序大量数据),优先使用 comparingInt/Long/Double 版本。
  • ToIntFunction<T> 是一个函数式接口,它接受一个对象,返回一个 int。
  • 同理,ToLongFunction<T> 和 ToDoubleFunction<T> 也类似。

💬 举个练习题

请根据以下 Product 类,按价格升序排序(double),如果价格相同,再按库存(int)升序排序:

java 复制代码
class Product {
    private String name;
    private double price;
    private int stock;

    // Getter 省略
}

你会写出:

java 复制代码
Comparator<Product> comparator = 
    Comparator.comparingDouble(Product::getPrice)
              .thenComparingInt(Product::getStock);
相关推荐
椒颜皮皮虾྅几秒前
让 C# 读懂整张图:DeploySharp 驱动 PaddleOCR v4/v5/v6,打通 OCR 全流程
开发语言·人工智能·深度学习·学习·c#·ocr·cuda
昂好的day4 分钟前
C# 同步异步与多线程:Thread / Task / 线程池一次讲透(上篇)
开发语言·windows·c#
Java后端的Ai之路6 分钟前
01、Java并发编程:学习攻略如何才能学好并发编程?
java·开发语言·学习
ScilogyHunter23 分钟前
Hercules系列安全MCU功能安全原理详解
java·单片机·安全·hercules
博风42 分钟前
eclipse中配置maven,以及在本地使用maven。
java·eclipse·maven
云-缩影42 分钟前
实际项目中怎么选排序算法:从面试题到工程落地
java·算法·排序算法
追星星の人44 分钟前
java web项目(eclipse软件)全流程备份
java·servlet
OxYGC44 分钟前
[工程] PHP2Shell 漏洞解析:两条 PHP 内核 RCE,为什么应用层的防护全部失效
android·开发语言·php
小徐不徐说1 小时前
数据库存储基础:理解表结构、主键、事务与 BLOB
开发语言·数据库·c++·qt·程序设计
草莓熊Lotso1 小时前
【C++ 基于微服务的即时通讯系统】网关基建:cpp-httplib 与 WebSocketpp 从入门到实战
linux·开发语言·数据库·c++·redis·微服务·云原生