关于Comparator.comparingInt的Lambda与方法引用使用及原理的咨询
你的测试代码
public static void main(String[] args) { Student[] students = new Student[4]; students[0] = new Student("guy1", 103, 334); // height / age (随便写的) students[1] = new Student("guy2", 87, 534); students[2] = new Student("guy3", 103, 232); students[3] = new Student("guy4", 110, 121); Arrays.sort(students, Comparator.comparingInt(Student::getAge)); // 方法引用 Arrays.sort(students, Comparator.comparingInt(student -> student.getAge())); // Lambda表达式 }
comparingInt方法源码
// comparingInt方法的源码 public static <T> Comparator<T> comparingInt(ToIntFunction<? super T> keyExtractor) { Objects.requireNonNull(keyExtractor); return (Comparator<T> & Serializable) (c1, c2) -> Integer.compare(keyExtractor.applyAsInt(c1), keyExtractor.applyAsInt(c2)); }
你尝试过的错误写法
// 类似这样的写法都无法通过IDEA校验 Arrays.sort(students, Comparator.comparingInt(students,c1,getAge)); // 你熟悉的匿名内部类写法(对比用) // Animal a = new Animal() { // @Override // public void run() { // System.out.println("dog runs"); // } // }; // Animal a = () -> { // System.out.println("dog runs"); // }; // // a.run();
核心问题解答
1. 为什么不能直接传对象和方法?
comparingInt要的不是具体的Student对象或者方法本身,而是一个**“从任意Student对象中提取int类型值”的规则**——这个规则由ToIntFunction接口定义:接收一个T类型(这里是Student)的参数,返回int。
你尝试的comparingInt(students,c1,getAge)写法完全不符合参数要求,因为该方法只接受一个参数:实现了ToIntFunction的实例,而非一堆对象、变量名。
2. Lambda和方法引用为什么能行?
它们本质上都是ToIntFunction接口的简化实现,和你写Animal的匿名内部类逻辑一致:
- Lambda表达式:
student -> student.getAge()就是在实现ToIntFunction的applyAsInt方法——输入一个Student对象,返回它的age值。 - 方法引用:
Student::getAge是Lambda的语法糖,因为getAge()方法的签名刚好匹配ToIntFunction的要求:接收Student,返回int,编译器会自动把它适配成ToIntFunction的实例。
3. 结合源码看逻辑
从comparingInt的源码能清楚看到:
- 它接收的
keyExtractor是提取规则,返回一个Comparator。 - 这个返回的
Comparator在比较两个对象c1和c2时,会调用keyExtractor.applyAsInt(c1)和keyExtractor.applyAsInt(c2),拿到两个int值后用Integer.compare做比较。
也就是说,你不需要提前给它具体的Student对象,排序时Arrays.sort会自动把数组里的每一对Student对象传给这个Comparator,而keyExtractor负责从每个对象里拿出要比较的字段值——这才是这个方法的设计逻辑:把“提取比较字段”和“比较逻辑”解耦,你只需要告诉它怎么拿值,剩下的比较逻辑由方法帮你实现。
4. 对比你熟悉的匿名内部类
如果不用Lambda和方法引用,用匿名内部类写ToIntFunction的话,是这样的:
Comparator<Student> comparator = Comparator.comparingInt(new ToIntFunction<Student>() { @Override public int applyAsInt(Student student) { return student.getAge(); } }); Arrays.sort(students, comparator);
和你写Animal的匿名内部类完全一样,Lambda和方法引用只是把这段代码简化成了一行而已。
内容的提问来源于stack exchange,提问作者Clarence
相关产品推荐
相关产品推荐

