JDK8-1-Lambda表达式(5)-复合 Lambda 表达式

JDK8-1-Lambda表达式(5)-复合 Lambda 表达式

JDK8 在 java.util.function 包下定义了一些默认的 函数式接口 ,如 Predicate、Consumer、Function、
Comparator (在 java.util.包下) ,这些接口提供了一些复合的方法,允许将简单的 Lambda 表达式复合成复杂的的表达式,下面以这些接口为例解释下复合方法的使用:

java.util.function.Predicate

negate

返回表示此谓词的逻辑否定的谓词。

/**
 * Returns a predicate that represents the logical negation of this
 * predicate.
 *
 * @return a predicate that represents the logical negation of this
 * predicate
 */
default Predicate negate() {
    return (t) -> !test(t);
}

如下例所示:
greenApplePredicate 表示返回绿色的苹果,而 greenApplePredicate.negate 则表示返回非绿色的苹果

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class ComplexTest {
    private static final List apples = Arrays.asList(
            new Apple("red", 400), new Apple("green", 300),
            new Apple("yellow", 100), new Apple("green", 200)
    );

    public static void main(String[] args) {
        Predicate greenApplePredicate = apple -> "green".equals(apple.getColor());
        Predicate notGreenApplePredicate = greenApplePredicate.negate();

        List notGreenApples =  apples.stream().filter(notGreenApplePredicate).collect(Collectors.toList());
        System.out.println(notGreenApples);
    }
}

打印结果:

[Apple{color='red', weight=400.0}, Apple{color='yellow', weight=100.0}]

and

and 方法入参为一个新的 Predicate 类型对象,返回一个组合谓词,该谓词表示此谓词与另一个谓词的逻辑与

/**
 * Returns a composed predicate that represents a short-circuiting logical
 * AND of this predicate and another.  When evaluating the composed
 * predicate, if this predicate is {@code false}, then the {@code other}
 * predicate is not evaluated.
 *
 * 

Any exceptions thrown during evaluation of either predicate are relayed * to the caller; if evaluation of this predicate throws an exception, the * {@code other} predicate will not be evaluated. * * @param other a predicate that will be logically-ANDed with this * predicate * @return a composed predicate that represents the short-circuiting logical * AND of this predicate and the {@code other} predicate * @throws NullPointerException if other is null */ default Predicate and(Predicate other) { Objects.requireNonNull(other); return (t) -> test(t) && other.test(t); }

举例说明:
下例中,greenApplePredicate 表示返回绿色苹果,heavyApplePredicate 表示返回重的苹果,
greenApplePredicate.and(heavyApplePredicate) 则表示绿色且重的苹果

public class ComplexAndTest {
    private static final List apples = Arrays.asList(
            new Apple("red", 400), new Apple("green", 300),
            new Apple("yellow", 100), new Apple("green", 200)
    );

    public static void main(String[] args) {
        Predicate greenApplePredicate = apple -> "green".equals(apple.getColor());
        Predicate heavyApplePredicate = apple -> apple.getWeight() > 200;

        List greenAndHeavyApples = apples.stream()
                .filter(greenApplePredicate.and(heavyApplePredicate)).collect(Collectors.toList());
        System.out.println(greenAndHeavyApples);
    }
}

打印结果:

[Apple{color='green', weight=300.0}]

or

返回表示此谓词和另一个谓词的 逻辑或 的组合谓词。

/**
 * Returns a composed predicate that represents a short-circuiting logical
 * OR of this predicate and another.  When evaluating the composed
 * predicate, if this predicate is {@code true}, then the {@code other}
 * predicate is not evaluated.
 *
 * 

Any exceptions thrown during evaluation of either predicate are relayed * to the caller; if evaluation of this predicate throws an exception, the * {@code other} predicate will not be evaluated. * * @param other a predicate that will be logically-ORed with this * predicate * @return a composed predicate that represents the short-circuiting logical * OR of this predicate and the {@code other} predicate * @throws NullPointerException if other is null */ default Predicate or(Predicate other) { Objects.requireNonNull(other); return (t) -> test(t) || other.test(t); }

下例表示过滤出绿色或者重的苹果

public class ComplexOrTest {
    private static final List apples = Arrays.asList(
            new Apple("red", 400), new Apple("green", 300),
            new Apple("yellow", 100), new Apple("green", 200)
    );

    public static void main(String[] args) {
        Predicate greenApplePredicate = apple -> "green".equals(apple.getColor());
        Predicate heavyApplePredicate = apple -> apple.getWeight() > 200;

        List greenAndHeavyApples = apples.stream()
                .filter(greenApplePredicate.or(heavyApplePredicate)).collect(Collectors.toList());
        System.out.println(greenAndHeavyApples);
    }
}

打印:

[Apple{color='red', weight=400.0}, Apple{color='green', weight=300.0}, Apple{color='green', weight=200.0}]

and or 组合

下例表示从 apples 列表中筛选 ( 绿色 || 红色 ) && 重 的苹果

public class ComplexAndOrTest {
    private static final List apples = Arrays.asList(
            new Apple("red", 400), new Apple("green", 300),
            new Apple("yellow", 100), new Apple("green", 200)
    );

    public static void main(String[] args) {
        Predicate greenApplePredicate = apple -> "green".equals(apple.getColor());
        Predicate redApplePredicate = apple -> "red".equals(apple.getColor());
        Predicate heavyApplePredicate = apple -> apple.getWeight() > 200;

        List appleList = apples.stream()
                .filter(greenApplePredicate.or(redApplePredicate).and(heavyApplePredicate)).collect(Collectors.toList());
        System.out.println(appleList);
    }

}

请注意,and和or方法是按照在表达式链中的位置,从左向右确定优先级的。因此,a.or(b).and(d)可以看作(a || b) && d。

java.util.function.Function

andThen

表示先执行 apply 中逻辑,将入参(T t)传入 apply执行 返回结果(R ),R 作为入参后执行 after.apply 逻辑返回结果 V,所以 andThen 泛型定义为 Function
其中 ? super R 表示 为 R的父类,? extends V 表示为 V 的子类

/**
 * Returns a composed function that first applies this function to
 * its input, and then applies the {@code after} function to the result.
 * If evaluation of either function throws an exception, it is relayed to
 * the caller of the composed function.
 */
default  Function andThen(Function after) {
    Objects.requireNonNull(after);
    return (T t) -> after.apply(apply(t));
}

由下例可以看出执行逻辑的顺序:

import java.util.function.Function;

public class ComplexFunTest1 {
    public static void main(String[] args) {
        Function f = x -> x + 1;
        Function g = x -> x * 2;
        Function h = f.andThen(g);
        int result = h.apply(1);
        System.out.println(result);
    }
}

结果:

4

compose

与 andThen 逻辑相反,compose 逻辑是先执行 before.apply ,得到返回结果后作为入参再执行 apply

/**
 * Returns a composed function that first applies the {@code before}
 * function to its input, and then applies this function to the result.
 * If evaluation of either function throws an exception, it is relayed to
 * the caller of the composed function.
 */
default  Function compose(Function before) {
    Objects.requireNonNull(before);
    return (V v) -> apply(before.apply(v));
}

还是上面的例子, 不同的是 andThen 换成了 compose

import java.util.function.Function;

public class ComplexFunTest2 {
    public static void main(String[] args) {
        Function f = x -> x + 1;
        Function g = x -> x * 2;
        Function h = f.compose(g);
        int result = h.apply(1);
        System.out.println(result);
    }
}

执行结果:

3

JDK8-1-Lambda表达式(5)-复合 Lambda 表达式_第1张图片
来自《Java 8 实战》

java.util.Comparator

先看一个简单的排序例子:
按照重量对现有的苹果排序并打印结果。此处要注意的是直接使用 apples.sort(weightComparator);方法会改变原列表的顺序,使用 stream().sorted 则不会。

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

public class ComplexComparatorTest1 {
    private static final List apples = Arrays.asList(
            new Apple("red", 400), new Apple("green", 300),
            new Apple("yellow", 100), new Apple("green", 200)
    );

    public static void main(String[] args) {
        Comparator weightComparator = (a, b) -> a.getWeight().compareTo(b.getWeight());
        List applesSortedByWeight = apples.stream().sorted(weightComparator).collect(Collectors.toList());
        System.out.println(applesSortedByWeight);
        System.out.println(apples);
    }
}

打印结果:

[Apple{color='yellow', weight=100.0}, Apple{color='green', weight=200.0}, Apple{color='green', weight=300.0}, Apple{color='red', weight=400.0}]
[Apple{color='red', weight=400.0}, Apple{color='green', weight=300.0}, Apple{color='yellow', weight=100.0}, Apple{color='green', weight=200.0}]

另外,以下代码可以使用 Comparator.comparing 缩写

Comparator weightComparator = (a, b) -> a.getWeight().compareTo(b.getWeight());

缩写后:

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

Comparator.comparing 定义如下

public static > Comparator comparing(
            Function keyExtractor){
    Objects.requireNonNull(keyExtractor);
    return (Comparator & Serializable)
        (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
}

按照JDK8之前的语法理解,可以拆成如下写法:

Function f = new Function() {
   @Override
    public Double apply(Apple apple) {
        return apple.getWeight();
    }
};
Comparator weightComparator2 = new Comparator() {
    @Override
    public int compare(Apple a, Apple b) {
        return f.apply(a).compareTo(f.apply(b));
    }
};

相当于 Comparator.comparing 帮我们实例化一个 Comparator ,这个方法入参为 Function

reversed (逆序)

返回:一个比较器,它对这个比较器进行反向排序。

/**
 * Returns a comparator that imposes the reverse ordering of this
 * comparator.
 * @since 1.8
 */
default Comparator reversed() {
    return Collections.reverseOrder(this);
}

查看 reverseOrder 方法可知,此方法返回类型为 ReverseComparator2,而 ReverseComparator2 的 比较方法为:
可以明显看到方法中 t1,t2 顺序对调了

public int compare(T t1, T t2) {
    return cmp.compare(t2, t1);
}

使用如下:

public class ComplexComparatorTest2 {
    private static final List apples = Arrays.asList(
            new Apple("red", 400), new Apple("green", 300),
            new Apple("yellow", 100), new Apple("green", 200)
    );

    public static void main(String[] args) {
        Comparator weightComparator = Comparator.comparing(Apple::getWeight);
        List applesSortedByWeight =
                apples.stream().sorted(weightComparator.reversed()).collect(Collectors.toList());
        System.out.println(applesSortedByWeight);
    }
}

结果:

[Apple{color='red', weight=400.0}, Apple{color='green', weight=300.0}, Apple{color='green', weight=200.0}, Apple{color='yellow', weight=100.0}]

thenComparing 比较器链

下例表示按照苹果颜色排序并打印结果,由结果可以看出有两个绿色的苹果,它们按照原来的顺序排列的,如果要将颜色相同的苹果重新按照重量排序怎么做呢,

public class ComplexComparatorTest3 {
    private static final List apples = Arrays.asList(
            new Apple("red", 400), new Apple("green", 300),
            new Apple("yellow", 100), new Apple("green", 200)
    );

    public static void main(String[] args) {
        Comparator colorComparator = Comparator.comparing(Apple::getColor);
        List applesSortedByWeight =
                apples.stream().sorted(colorComparator).collect(Collectors.toList());
        System.out.println(applesSortedByWeight);
    }
}

输出结果:

[Apple{color='green', weight=300.0}, Apple{color='green', weight=200.0}, Apple{color='red', weight=400.0}, Apple{color='yellow', weight=100.0}]

thenComparing 就是用来解决这类问题的,看下它的定义:

default > Comparator thenComparing(
        Function keyExtractor){
    return thenComparing(comparing(keyExtractor));
}

由以下代码可以看出,如果 比较器 compare 不相等则用原结果值返回,否则表示相等,则用 下一个比较器 other.compare 值返回

default Comparator thenComparing(Comparator other) {
    Objects.requireNonNull(other);
    return (Comparator & Serializable) (c1, c2) -> {
        int res = compare(c1, c2);
        return (res != 0) ? res : other.compare(c1, c2);
    };
}

对以上代码进行改造:

Comparator colorComparator = Comparator.comparing(Apple::getColor);
        List applesSortedByWeight =
                apples.stream().sorted(colorComparator.thenComparing(Apple::getWeight)).collect(Collectors.toList());

打印结果如下:

[Apple{color='green', weight=200.0}, Apple{color='green', weight=300.0}, Apple{color='red', weight=400.0}, Apple{color='yellow', weight=100.0}]

你可能感兴趣的:(JavaSE,java,servlet,jvm)