Java Lambda从入门到精通七 复合lambda表达式

所谓的复合lambda表达式,就是多个lambda表达式可以组合在一起使用。

比如我们上一节对苹果集合按照重量进行排序,其中有一种排序是这样写的:

apples.sort(Comparator.comparing(Apple::getWeight).reversed());

我们使用Comparator.comparing(Apple::getWeight)先进行了默认升序排序,然后紧接这,使用了reversed()方法,将结果反转,这两个方法的就形成了连续的操作,这就是符合lambda。

比如我们在苹果重量相同的时候,想继续按照苹果产地进行排序:


import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.function.BiPredicate;

/**
 * @Auther: www.itzhimei.com
 * @Description: 行为参数化  使用lambda表达式简化代码
 */
public class Lambda4 {

    public static void main(String[] args) {
        List<Apple> apples = new ArrayList<>();
        Apple a1 = new Apple("红",155,"北京");
        Apple a2 = new Apple("绿",136,"上海");
        Apple a3 = new Apple("红",169,"广州");
        Apple a4 = new Apple("红",155,"深圳");
        apples.add(a1);
        apples.add(a2);
        apples.add(a3);
        apples.add(a4);

        System.out.println("---排序前---");
        apples.forEach(System.out::println);
        apples.sort(Comparator.comparing(Apple::getWeight).thenComparing(Apple::getPlaceOrigin));
        System.out.println("---排序后---");
        apples.forEach(System.out::println);
}

苹果实体:


import lombok.Data;

/**
 * @Auther: www.itzhimei.com
 * @Description:
 */
@Data
public class Apple {

    private String color;

    private int weight;

    public Apple(String color, int weight) {
        this.color = color;
        this.weight = weight;
    }
}

输出结果:

---排序前---
Apple(color=红, weight=155, placeOrigin=北京)
Apple(color=绿, weight=136, placeOrigin=上海)
Apple(color=红, weight=169, placeOrigin=广州)
Apple(color=红, weight=155, placeOrigin=深圳)
---排序后---
Apple(color=绿, weight=136, placeOrigin=上海)
Apple(color=红, weight=155, placeOrigin=北京)
Apple(color=红, weight=155, placeOrigin=深圳)
Apple(color=红, weight=169, placeOrigin=广州)

我们通过thenComparing对按照重量排序的结果又进行了产地排序,这样是不是很方便,想一下, 在Java8以前要这样实现需要怎么写,是不是在实现类或匿名类中实现一大坨代码。

lambda的这种复合分为两种,一种是谓词复合,另一种是函数复合。

谓词复合,根据前面的学习,你可能已经猜到了,这是配合Predicate使用的,Predicate中就已经有三个默认方法:negate、and和or,分别对应非、与、或。

我们举个例子,比如我本来想取苹果集合中的绿颜色苹果,现在我用negate取反:

Predicate<Apple> p1 = (Apple a) -> a.getColor().equals("绿");
        apples.forEach(a -> {
            if(p1.negate().test(a)) {
                System.out.println(a.getColor());
            }
        });

输出结果:

红
红
红

函数复合,是对Function进行复合应用。Function中提供了compose和andThen两个默认方法。

andThen如名字一样,先怎样,然后怎样。

Function<Integer, Integer> a = x -> x + 1; 
Function<Integer, Integear> b = x -> x - 1; 
Function<Integer, Integer> c = a.andThen(b);

andThen的效果相当于数学中的计算方式: b(a(x)),也就是先计算 a(x),然后根据a(x)的结果计算b函数。

compose正好相反,上面这段代码使用compose:

Function<Integer, Integer> a = x -> x + 1; 
Function<Integer, Integear> b = x -> x - 1; 
Function<Integer, Integer> c = a.compose(b);

实际执行效果是:a(b(x))