Java8:复合Lambda 表达式

Java 8的好几个函数式接口都有为方便而设计的方法。具体而言,许多函数式接口,比如用于传递Lambda表达式的Comparator、Function和Predicate都提供了允许你进行复合的方法。
这是什么意思呢?在实践中,这意味着你可以把多个简单的Lambda复合成复杂的表达式。比如,你可以让两个谓词之间做一个or操作,组合成一个更大的谓词。而且,你还可以让一个函数的结果成为另一个函数的输入。
1.比较器的复合 我们前面看到,你可以使用静态方法Comparator.comparing,根据提取用于比较的键值的Function来返回一个Comparator,如下所示:

Comparator c = Comparator.comparing(Apple::getWeight);

1.1 逆序
【Java8:复合Lambda 表达式】如果你想要对苹果按重量递减排序怎么办?用不着去建立另一个Comparator的实例。接口有一个默认方法reversed可以使给定的比较器逆序。因此仍然用开始的那个比较器,只要修改一下前一个例子就可以对苹果按重量递减排序:
// 按重量递减排序 inventory.sort(comparing(Apple::getWeight).reversed());

2. 1 比较器链
如果发现有两个苹果一样重怎么办?哪个苹果应该排在前面呢?你可能
需要再提供一个Comparator来进一步定义这个比较。比如,在按重量比较两个苹果之后,你可能想要按原产国排序。thenComparing方法就是做这个用的。它接受一个函数作为参数(就像comparing方法一样),如果两个对象用第一个Comparator比较之后是一样的,就提供第二个Comparator。你又可以优雅地解决这个问题了:
// 先按重量递减排序,如果两个苹果一样重的时候,进一步按照国家排序 inventory.sort(comparing(Apple::getWeight) .reversed() .thenComparing(Apple::getCountry));

2. 谓词复合 谓词接口包括三个方法:negate、and和or,让你可以重用已有的Predicate来创建更复杂的谓词。
比如,你可以使用negate方法来返回一个Predicate的非,比如苹果不是红的:
// 产生现有Predicate对象redApple的非 Predicate notRedApple = redApple.negate();

你可能想要把两个Lambda用and方法组合起来,比如一个苹果既是红色又比较重:
// 链接两个谓词来生成另一个Predicate对象 Predicate redAndHeavyApple =redApple.and(a -> a.getWeight() > 150);

你可以进一步组合谓词,表达要么是重(150克以上)的红苹果,要么是绿苹果:
Predicate redAndHeavyAppleOrGreen = redApple.and(a -> a.getWeight() > 150) .or(a -> "green".equals(a.getColor()));

这一点为什么很好呢?从简单Lambda表达式出发,你可以构建更复杂的表达式,但读起来仍然和问题的陈述差不多!请注意,and和or方法是按照在表达式链中的位置,从左向右确定优先级的。因此,a.or(b).and(c)可以看作(a || b) && c。

    推荐阅读