您的位置:首页 > 编程语言 > Java开发

【JAVA Lambda】初学者对Comparator.comparing(Person::getLastName).thenComparing(Person::getFirstName)套娃的理解

2020-04-07 17:23 113 查看

最近在看《JAVA 核心技术 卷一》 对Comparator.comparing().thenComparing()这个套娃有点不解然后研究了一下。

Arrays.sort(person, Comparator.comparing(Person::getLastName).thenComparing(Person::getFirstName));

一、静态方法comparing(Function<? super T, ? extends U> keyExtractor)

//comparing()方法
static <T, U extends Comparable<? super U>> Comparator<T> comparing(Function<? super T, ? extends U> keyExtractor) {
Objects.requireNonNull(keyExtractor);
return (Comparator)((Serializable)((c1, c2) -> {
return ((Comparable)keyExtractor.apply(c1)).compareTo(keyExtractor.apply(c2));
}));
}

----1. 先看传入的参数

因为Function是一个被@FunctionalInterface修饰的接口(表示其中只有一个必须实现的方法)即可以用lambda表达式

Person::getLastName()是【方法引用】相当于lambda:(Person P)->{P.getLastName()}
//根据comparing的参数列表可知传入的Person::getLastName相当于下列代码
Function<Person,String> keyExtractor=(Person P)->P.getLastName();

----2.Objects.requireNonNull(keyExtractor)

//貌似是判断非空的,暂时不管他(其实是我暂时不知道2333)
Objects.requireNonNull(keyExtractor)

----3.comparing方法中最关键的部分

return (Comparator)((Serializable)((c1, c2) -> {
return ((Comparable)keyExtractor.apply(c1)).compareTo(keyExtractor.apply(c2));
}));

------------1)先看最里层,是一个lambda表达式

(c1, c2) -> {return ((Comparable)keyExtractor.apply(c1)).compareTo(keyExtractor.apply(c2));}

------------2)当中用到了传入的Function keyExtractor,我们将它用Person::getLastName替换便于理解

(c1, c2) -> {return ((Comparable)Person.getLastName(c1)).compareTo(Person.getLastName(c2));}

------------3)然后是一个(Comparable)的类型转换,comparing()方法中最关键的部分结束

因为要使用Comparable接口里的compareTo()比较方法,所以要进行类型转换

----4.最后comparing方法将lambda表达式转换成Comparato对象返回(Serializable好像是序列化的意思,暂时没有研究2333)

二、默认方法 default <U extends Comparable<? super U>> Comparator thenComparing(Function<? super T, ? extends U> keyExtractor)

default <U extends Comparable<? super U>> Comparator<T> thenComparing(Function<? super T, ? extends U> keyExtractor) {
return this.thenComparing(comparing(keyExtractor));
}
分析过comparing()之后thenComparing()就非常简单了
过程:调用comparing()返回一个Comparator对象,然后将Comparator对象传入this.thenComparing()得到一个符合<U extends Comparable<? super U>>的Comparable类对象

三、被上一方法套娃调用的this.thenComparing()

default Comparator<T> thenComparing(Comparator<? super T> other) {
Objects.requireNonNull(other);
return (Comparator)((Serializable)((c1, c2) -> {
//调用第一次comparing()方法所生成的Comparator对象的compare()方法
//(comparing(Person::getLastName)生成的)
int res = this.compare(c1, c2);
//如果res为0,两String相等,就调用第二次comparing()方法所生成的Comparator对象的compare()方法
//(thenComparing(Person::getFirstName)中comparing(keyExtractor)生成的)
return res != 0 ? res : other.compare(c1, c2);
}));
}
这个方法的作用就是将被comparing()方法转换完的Comparator对象整合成一个lambda表达式然后转换成Comparator对象返回。

四、总结

comparing():创建第一个比较分支
thenComparing():创建其它比较分支并调用this.thenComparing()
this.thenComparing():整合比较分支
有点单支二叉树的感觉(不知道是不是错觉)每一个节点就是一个判断条件(例:Person::getLastName)相等就继续往下,不相等就结束


发现不懂的地方还很多,比如泛型那一堆尖括号类似<? super T, ? extends U>这种还有Serializable、Objects.requireNonNull之类的。

如果有错误请帮忙指出。Thanks♪(・ω・)ノ

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: