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

文章介绍了JDK8中Lambda表达式的复合使用,包括Predicate接口的negate、and、or方法,用于构建复杂的逻辑判断。同时讲解了Function的andThen和compose方法,以及Comparator的使用,如sorting、reversed和thenComparing,展示了如何对数据进行多条件排序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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>() {
   @Override
    public Double apply(Apple apple) {
        return apple.getWeight();
    }
};
Comparator<Apple> weightComparator2 = new Comparator<Apple>() {
    @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<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}]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值