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);