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

news2025/2/1 4:13:26

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/631479.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

运营-21.常见的内容生产方式

常见的 内容生产方式 PGC&#xff08;Professionally-generated Content&#xff09;专业生产内容 传统的门户网站内容生产方式&#xff0c;内容多由官方工作人员身或者专业的内容创造者&#xff08;比如新闻记者等&#xff09;创造。 UGC&#xff08;User Generated Content&a…

【好书精读】网络是怎样连接的 浏览器生成消息

如果只是讲解 TCP/IP 、 以太网这些单独的技 术 &#xff0c; 读者就无法理解网络这个系统的全貌 &#xff1b; 如果无法理解网络的全貌 &#xff0c; 也 就无法理解每一种网络技术背后的本质意义 &#xff1b; 而如果无法理解其本质意义 &#xff0c; 就只能停留在死记硬背的…

MMDetection代码实战

title: mmdet代码实战 date: 2023-06-10 17:01:45 tags: [detection,pytorch] MMDetection代码实战 这一届主要讲解了&#xff0c;如何构建cfg&#xff0c;如何在目标检测上设置自己的配置文件。主要的思维导图如下 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下…

第3章“程序的机器级表示”:对齐(alignment)

许多计算机系统对基本数据类型的可允许地址做出了一些限制&#xff0c;要求某种类型的对象的地址必须是某个值 k k k &#xff08;通常是2、4 或 8&#xff09;的倍数。这种 对齐限制 简化了处理器和存储器系统之间接口的硬件设计。例如&#xff0c;假设一个处理器总是从存储器…

pikachu靶场-File Inclusion

文件包含漏洞概述 在web后台开发中&#xff0c;程序员往往为了提高效率以及让代码看起来更加简介&#xff0c;会使用”包含“函数功能。比如把一系列功能函数都写进function.php中&#xff0c;之后当某个文件需要调用的时候就直接在文件头上写上一句<?php include functio…

多叉树的构建,条件查询,修改删除节点

多叉树的构建查询&#xff0c;新增&#xff0c;修改&#xff0c;删除 文章目录 多叉树的构建查询&#xff0c;新增&#xff0c;修改&#xff0c;删除一&#xff0c;数据库表设计二、新增相对应数据库表的实体类三、新建多叉树树工具类四、多叉树树的条件查询五、多叉树的节点新…

关于【Git】push失败与使用小乌龟(TortoiseGit)时的一些报错解决方案

1.报错:No supported authentication methods available (server sent: publickey) 原因.小乌龟没有设置git路径&#xff0c;解决如下 将红框标注的地址改为自己的git安装地址即可。 2.使用git推送到远程仓库的时候报错Failed to connect to 127.0.0.1 port 7890: 拒绝连接 …

C# 让程序代码在固定的线程里运行

一、概述 在平时我们的开发中&#xff0c;多线程也是经常用到的&#xff0c;尤其是我们做上位机行业的&#xff0c;平时更是必不可少&#xff0c;在以前我做 Unity3d 开发时&#xff0c;其实并不用关心线程的问题&#xff0c;在 Unity 的开发中&#xff0c;所有代码基本都是单…

点云综述(整理自网络资源)

目录 一、什么是点云 二、如何获取点云 1、三维激光扫描仪 2、双目相机 双目测距基本原理 视差图 双目测距的优点与难点 3、RGB-D相机 RGB-D什么意思 RGB-D相机的分类 RGBD相机的缺点&#xff1a; RGBD相机的优点 三、点云有哪些研究方向 1、基于点云的分类 2、基于…

华为OD机试真题 JavaScript 实现【IPv4地址转换成整数】【2023 B卷 100分】

一、题目描述 存在一种虚拟 IPv4 地址&#xff0c;由4小节组成&#xff0c;每节的范围为0~255&#xff0c;以#号间隔&#xff0c; 虚拟 IPv4 地址可以转换为一个32位的整数&#xff0c;例如&#xff1a; 128#0#255#255&#xff0c;转换为32位整数的结果为2147549183&#xff0…

【深入理解函数栈帧:探索函数调用的内部机制】

本章我们要介绍的不是数学中的函数&#xff0c;而是C语言中的函数哟&#xff01; 本章重点 了解汇编指令深刻理解函数调用过程 样例代码&#xff1a; #include <stdio.h> int MyAdd(int a, int b) {int c 0;c a b;return c; }int main() {int x 0xA;int y 0xB;int…

SpringCloud第二篇:Feign远程调用

思考&#xff1a;为啥要学Feign呢&#xff1f; 先来看我们以前利用RestTemplate发起远程调用的代码&#xff1a; String url "http://userservice/user/" order.getUserId(); User user restTemplate.getFor0bject(url,User.class);这里就有几个问题&#xff1a…

首届“设计·无尽谈”论坛完满收官 持续打造当代设计共同体

首届“设计无尽谈”论坛在京举行 5月16日&#xff0c;首届“设计无尽谈”论坛在北京举行&#xff0c;本次论坛以“漫谈当代空间精神”为主题&#xff0c;12位来自顶尖建筑设计领域的嘉宾和设计师到场&#xff0c;论坛以茶话会的形式进行&#xff0c;不受严格的议程和时间限制的…

计算机网络之网络层

四.网络层&#xff1a;数据平面 4.1 网络层概述 网络层被分解为两个相互作用的部分&#xff0c;即数据平面和控制平面。 数据平面决定到达路由器输入链路之一的数据报如何转发到该路由器的输出链路之一&#xff0c;转发方式有&#xff1a; 传统的IP转发&#xff1a;转发基于…

Nginx(一)介绍Nginx、正向代理和实现反向代理的两个实例

文章目录 一、Nginx介绍二、正向代理三、反向代理四、实例演示1、反向代理实例一&#xff08;反向代理&#xff0c;访问www.123.com&#xff09;2、反向代理实例二&#xff08;使用 nginx 反向代理&#xff0c;根据访问的路径跳转到不同端口的服务中&#xff09; 五、nginx之lo…

文件操作之文件下载(32)

下载和读取是差不多的情况 区分 文件被解析&#xff0c;我们称为文件包含漏洞 显示文件的源代码&#xff0c;我们称为文件读取漏洞 提示文件下载&#xff0c;我们称为文件下载漏洞 #文件下载 文件下载出现的原因&#xff0c;在任意代码里面出现下载性的功能性函数所导致的…

调用腾讯API实现人像分割

目录 1. 作者介绍2&#xff0e;腾讯云API人像分割2.1 人像分割接口描述2.2 请求参数介绍 3&#xff0e;代码实现3.1 获取SecretId和SecretKey3.2 人像分割代码调试3.3 完整代码3.4 实验结果 1. 作者介绍 岳泽昂&#xff0c;男&#xff0c;西安工程大学电子信息学院&#xff0c…

MySQL主从同步——主库已有的数据如何到从库

一、复制主库数据到从库 此步骤主要针对运行一段时间的主库&#xff0c;需要将历史数据导入到从库&#xff0c;保证主从强一致性。 主库锁表停止写操作 在主库MySQL命令行中执行 flush tables with read lock; 主库数据导出 将主库所在主机命令行下使用mysqldump命令导出…

交通状态分析 | Python实现基于张量分解的交通流量时空模式挖掘

文章目录 效果一览文章概述研究内容源码设计参考资料效果一览 文章概述 交通状态分析 | Python实现基于张量分解的交通流量时空模式挖掘 研究内容 一般出行行程通常都由某种明确目的驱使,例如上班、购物或娱乐,出行的起始区域因其承担功能的不同,通常能够反映出用户的出行目…

【一、Linux文件与目录结构】

1 Linux 文件 Linux系统中一切皆文件 2 Linux目录结构 /bin Binary的缩写&#xff0c;存放着命令。 /sbin s即Super User&#xff0c;存放着root用户使用的系统管理程序。 /home 存放着普通用户的主目录&#xff0c;在Linux中每个用户都有一个自己的目录&#xff0c;一般…