JDK8 在 java.util.function 包下定义了一些默认的 函数式接口 ,如 Predicate、Consumer、Function、
Comparator (在 java.util.包下) ,这些接口提供了一些复合的方法,允许将简单的 Lambda 表达式复合成复杂的的表达式,下面以这些接口为例解释下复合方法的使用:
返回表示此谓词的逻辑否定的谓词。
/**
* 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 方法入参为一个新的 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 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 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}]
返回表示此谓词和另一个谓词的 逻辑或 的组合谓词。
/**
* 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 super T> 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}]
下例表示从 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。
表示先执行 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 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 f = x -> x + 1;
Function g = x -> x * 2;
Function h = f.andThen(g);
int result = h.apply(1);
System.out.println(result);
}
}
结果:
4
与 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 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 f = x -> x + 1;
Function g = x -> x * 2;
Function h = f.compose(g);
int result = h.apply(1);
System.out.println(result);
}
}
执行结果:
3
先看一个简单的排序例子:
按照重量对现有的苹果排序并打印结果。此处要注意的是直接使用 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);
public static > Comparator comparing(
Function super T, ? extends U> 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
返回:一个比较器,它对这个比较器进行反向排序。
/**
* 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}]
下例表示按照苹果颜色排序并打印结果,由结果可以看出有两个绿色的苹果,它们按照原来的顺序排列的,如果要将颜色相同的苹果重新按照重量排序怎么做呢,
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 super T, ? extends U> keyExtractor){
return thenComparing(comparing(keyExtractor));
}
由以下代码可以看出,如果 比较器 compare 不相等则用原结果值返回,否则表示相等,则用 下一个比较器 other.compare 值返回
default Comparator thenComparing(Comparator super T> 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}]