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

news/2025/1/13 3:20:35/

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}]

http://www.ppmy.cn/news/314802.html

相关文章

UniApp组件封装

什么是UniApp组件&#xff1f; UniApp是一个跨平台的开发框架&#xff0c;允许开发者使用Vue.js编写一次代码&#xff0c;然后将其发布到多个平台&#xff0c;包括iOS、Android和Web。在UniApp中&#xff0c;组件是构建用户界面的基本单元&#xff0c;它们可以重复使用&#x…

Webots R2021a教程

文章目录 Windows安装设置中文打开世界添加贴图 为外部控制器配置Anaconda解决报错&#xff1a;CondaSSLError: Encountered an SSL error. Most likely a certificate verification issue.调用Python API Windows 安装 进入下载页面 https://github.com/cyberbotics/webots/r…

三星Android升级吗,三星Android 6.0升级名单一览 这次升级的系统有你的手机吗?

Android6.0 发布之后&#xff0c;三星公布了首批可升级的设备名单&#xff0c;然而让人失望的是去年的旗舰 S5 竟然不在其中&#xff0c;不过三星显然已经听到了用户的不满&#xff0c;在最新曝光的升级名单中&#xff0c;Galaxy S5 和 Galaxy Alpha 两款设备被加入第一批升级名…

三星手机出现红字your phone couldn’t start normally. some configuration data may be corrupt.

早上重启了一下三星S10手机出现如下情况 [caption id"attachment_321" align"alignnone" width"600"] 三星[/caption] 然后就再也开不了机了&#xff0c;选啥都没用. 选了第二个又出现这个 [caption id"attachment_322" align&quo…

linux怎么查询服务器信息,Linux查看服务器硬件信息的方法步骤

Hi&#xff0c;大家好&#xff1b;今天是双12,大家剁手了没。今天给大家带来的是《Linux查看服务器上的硬件信息》本篇文章的示例全部是在服务器(Inspur SA5112M4)上实现的&#xff0c;有些命令在虚拟机上达不到效果 查看服务器型号、序列号 rootzhangdaifu# dmidecode -s syst…

安卓应用在各大应用市场上架方法整理

想要把APP上架到应用市场都要先注册开发者账号才可以。这里的方法包括注册帐号和后期上架及一些需要注意的问题。注意&#xff1a;首次提交应用绝对不能随便删除&#xff0c;否则后面再提交会显示应用APP冲突&#xff0c;会要求走应用认领流程&#xff0c;那个时候就会相当麻烦…

Alexa Top 1000 在中国的访问情况

记录日期&#xff1a;2018.9.27 标题测试开始于Censored*google.com3月 2011100%youtube.com2月 2011100%facebook.com2月 2011100%twitter.com2月 2011100%instagram.com5月 2012100%google.co.in2月 2011100%blogspot.com2月 2011100%pornhub.com3月 2011100%google.ru3月 2…

透过三星/Intel/美光/东芝看2016年固态存储技术发展趋势

主控&#xff1a;更多的PCI-E和NVMe&#xff0c;想玩TLC先得有LDPC 接下来就是主控了&#xff0c;要把TLC闪存用得好是要求主控有一个比较好的纠错技术的&#xff0c;为了对应TLC闪存的到来&#xff0c;主控也开始加入了更高级的LDPC纠错技术&#xff0c;还有就是要准备好对应即…