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<T> 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<Apple> 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<Apple> greenApplePredicate = apple -> "green".equals(apple.getColor());Predicate<Apple> notGreenApplePredicate = greenApplePredicate.negate();List<Apple> 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.** <p>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<T> and(Predicate<? super T> other) {Objects.requireNonNull(other);return (t) -> test(t) && other.test(t);
}
举例说明:
下例中,greenApplePredicate 表示返回绿色苹果,heavyApplePredicate 表示返回重的苹果,
greenApplePredicate.and(heavyApplePredicate) 则表示绿色且重的苹果
public class ComplexAndTest {private static final List<Apple> 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<Apple> greenApplePredicate = apple -> "green".equals(apple.getColor());Predicate<Apple> heavyApplePredicate = apple -> apple.getWeight() > 200;List<Apple> 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.** <p>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<T> or(Predicate<? super T> other) {Objects.requireNonNull(other);return (t) -> test(t) || other.test(t);
}
下例表示过滤出绿色或者重的苹果
public class ComplexOrTest {private static final List<Apple> 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<Apple> greenApplePredicate = apple -> "green".equals(apple.getColor());Predicate<Apple> heavyApplePredicate = apple -> apple.getWeight() > 200;List<Apple> 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<Apple> 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<Apple> greenApplePredicate = apple -> "green".equals(apple.getColor());Predicate<Apple> redApplePredicate = apple -> "red".equals(apple.getColor());Predicate<Apple> heavyApplePredicate = apple -> apple.getWeight() > 200;List<Apple> 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<T, V>
其中 ? 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 <V> Function<T, V> andThen(Function<? super R, ? extends V> 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<Integer, Integer> f = x -> x + 1;Function<Integer, Integer> g = x -> x * 2;Function<Integer, Integer> 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 <V> Function<V, R> compose(Function<? super V, ? extends T> 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<Integer, Integer> f = x -> x + 1;Function<Integer, Integer> g = x -> x * 2;Function<Integer, Integer> h = f.compose(g);int result = h.apply(1);System.out.println(result);}
}
执行结果:
3
来自《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<Apple> 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<Apple> weightComparator = (a, b) -> a.getWeight().compareTo(b.getWeight());List<Apple> 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<Apple> weightComparator = (a, b) -> a.getWeight().compareTo(b.getWeight());
缩写后:
Comparator<Apple> weightComparator = Comparator.comparing(Apple::getWeight);
Comparator.comparing 定义如下
public static <T, U extends Comparable<? super U>> Comparator<T> comparing(Function<? super T, ? extends U> keyExtractor){Objects.requireNonNull(keyExtractor);return (Comparator<T> & Serializable)(c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
}
按照JDK8之前的语法理解,可以拆成如下写法:
Function<Apple, Double> f = new Function<Apple, Double>() {@Overridepublic Double apply(Apple apple) {return apple.getWeight();}
};
Comparator<Apple> weightComparator2 = new Comparator<Apple>() {@Overridepublic 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<T> 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<Apple> 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<Apple> weightComparator = Comparator.comparing(Apple::getWeight);List<Apple> 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<Apple> 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<Apple> colorComparator = Comparator.comparing(Apple::getColor);List<Apple> 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 <U extends Comparable<? super U>> Comparator<T> thenComparing(Function<? super T, ? extends U> keyExtractor){return thenComparing(comparing(keyExtractor));
}
由以下代码可以看出,如果 比较器 compare 不相等则用原结果值返回,否则表示相等,则用 下一个比较器 other.compare 值返回
default Comparator<T> thenComparing(Comparator<? super T> other) {Objects.requireNonNull(other);return (Comparator<T> & Serializable) (c1, c2) -> {int res = compare(c1, c2);return (res != 0) ? res : other.compare(c1, c2);};
}
对以上代码进行改造:
Comparator<Apple> colorComparator = Comparator.comparing(Apple::getColor);List<Apple> 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}]