转自 http://www.wxueyuan.com/blog/articles/2017/10/20/1508487961684.html
在上一篇博客中我们一起学习了使用方法引用的方式来重复使用现有的方法并直接传递它们,方法引用能够进一步地简化我们的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<T> 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));
下图说明了这两个方法的区别