在上一篇博客中我们一起学习了使用方法引用的方式来重复使用现有的方法并直接传递它们,方法引用能够进一步地简化我们的 Lambda 表达式。在实际问题的处理中,有时候我们需要多个 Lambda 表达式同时进行工作,Java 同样允许我们将多个简单的 Lambda 表达式复合成一个更复杂,完成功能更多的复杂表达式。比如,我们可以将两个谓词做一个 or 的操作,从而组成一个更强大的谓词;或者我们可以让一个函数的结果变成另一个函数的输入(类似于链式处理)。
- 比较器复合(Comparator 的复合)
1.逆序比较器
- Comparator reversed() 返回一个逆序后的 Comparator
students.sort(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
// TODO Auto-generated method stub
return o1.getAvgScore().compareTo(o2.getAvgScore());
}
}.reversed());
2.比较器链
如果使用了上面的比较器后,发现两个学生的平均成绩相同,你可能希望此时按照它们的身高进行排列。此时我们就需要
Comparator thenComparing(Comparator<? super T> other)这个方法来设定当第一个比较器中比较的两个元素相同时该如何进行排序。
students.sort(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
// TODO Auto-generated method stub
return o1.getAvgScore().compareTo(o2.getAvgScore());
}
}.reversed().thenComparing(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
// TODO Auto-generated method stub
return o1.getHeight().compareTo(o2.getHeight());
}
}));
- 谓词复合(Predicate 复合)
谓词的接口中提供了:negate,and 和 or 三个方法,有点类似于我们逻辑运算符中的非,与还有或。比如:
Predicate<Student> highStudents = s -> s.getHeight()>=180;
比如我们想要获得身高小于 180cm 的学生:
Predicate<Student> notHighStudents = highStudents.negate();
我们还可以将两个谓词条件结合起来,比如获得身高大于 180cm,且平均分大于 90 的学生
Predicate<Student> highAndHighScoreStudents = highStudents.and(s -> s.getAvgScore()>90);
我们还可以进一步组合谓词,比如要不然是身高大于 180 且平均分大于 90 分,要不然是平均分小于 60 的学生
Predicate<Student> complicatedPredicate = highStudents.and(s -> s.getAvgScore()>90).or(s -> s.getAvgScore()<60);
这种复合的表达式满足了我们更多的需求,但是读起来确仍然和问题的陈述差不多。需要注意的是,and 和 or 方法是按照在表达式链中的位置,从左向右确定优先级的。因此 a.or(b).and(c)也可以看作是 (a||b) && c
- 函数复合
我们同样可以把 Function 接口所代表的 Lambda 表达式复合起来。Function 接口提供了两个 andThen 和 compose 两个默认方法,它们都会返回 Function 的一个实例。
andThen 方法会返回一个函数,它会将输入应用给调用这个方法的函数,再将结果应用给这个方法的参数函数。听起来有一些抽象,我们一起来看一个例子:
Function<Integer,Integer> f = x ->x + 1;
Function<Integer,Integer> g = x ->x * 2;
//先将参数x传入给调用andThen方法的f函数,再将f函数的结果传给andThen方法的参数g函数,得到返回值
Function<Integer,Integer> h = f.andThen(g);
//结果返回是4
System.out.println(h.apply(1));
相似的 compose 方法,执行顺序与 andThen 相反,它会先将输入应用给方法参数的函数,再将结果应用给调用这个方法的函数,还是上面的那个例子:
Function<Integer,Integer> f = x ->x + 1;
Function<Integer,Integer> g = x ->x * 2;
//先将参数x传入给compose方法的参数g函数,再将g函数的结果传给调用compose方法的f函数,得到返回值
Function<Integer,Integer> h = f.compose(g);
//结果返回是3
System.out.println(h.apply(1));
下图说明了这两个方法的区别
各位同学,到这里,博主就已经用五篇博客将行为参数化,Lambda 表达式(一),Lambda 表达式(二),方法引用,复合 Lambda 表达式这几个重要的概念介绍了一遍。如果大家觉得哪里写的有问题,欢迎大家与我一起讨论。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于