JDK8新特性-Function接口与BiFunction接口

2023-10-27

Function 接口

  • JDK8新增的函数式接口
  • 接口只有一个抽象方法apply, 接受一个T类型参数, 返回一个R类型参数, T, R表示泛型, 可以相同
  • 除了一个抽象的apply方法之外, Function存在两个默认的default方法, compose和andThen, 这两个方法都是用来组合不同的Function的
  • 这个函数式接口被大量应用于集合以及Stream(流)中

apply 方法

/**
 * 输入一个T类型的参数
 * 返回一个R类型的值
 */
R apply(T t);

compose 方法

/**
 * 接口默认方法
 * 组合两个函数方法, 返回一个新的函数
 * before的apply方法输入一个V类型的参数, 返回一个T类型的参数
 * 当前的Funtion的apply方法是输入一个T类型的参数, 返回一个R类型的参数
 * 两个函数组合之后, 返回一个新的Function, 新的Function输入一个V类型的参数, 返回一个R类型的参数
 * 简单来说, 入参功能 : V -> T, 当前函数功能 : T -> R, 返回函数功能 : V -> R
 */
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
    // 非空判断
    Objects.requireNonNull(before);
    return (V v) -> apply(before.apply(v));
}

andThen 方法

/**
 * 组合两个函数方法, 返回一个新的函数
 * after的apply方法输入一个R类型的参数, 返回一个V类型的参数
 * 当前的Funtion的apply方法是输入一个T类型的参数, 返回一个R类型的参数
 * 两个函数组合之后, 返回一个新的Function, 新的Function输入一个T类型的参数, 返回一个V类型的参数
 * 简单来说, 入参功能 : R -> V, 当前函数功能 : T -> R, 返回函数功能 : T -> V
 */
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
    // 非空判断
    Objects.requireNonNull(after);
    return (T t) -> after.apply(apply(t));
}

API使用样例

    public static void main(String[] args) {
        Function<Integer, Integer> function1 = value -> value * 2;
        Function<Integer, Integer> function2 = value -> value + 3;
        Function<Integer, Integer> function3 = function1.compose(function2);
        Function<Integer, Integer> function4 = function1.andThen(function2);
        // function3,先执行function2的apply方法再执行function1的apply方法, 所以结果为(2 + 3) * 2 = 10
        System.out.println("function3 : " + function3.apply(2));
        // function4,先执行function1的apply方法再执行function2的apply方法, 所以结果为2 * 2 + 3 = 7
        System.out.println("function4 : " + function4.apply(2));

        Function<Integer, String> function5 = value -> "Hello World " + value;
        Function<String, List<String>> function6 = value -> new ArrayList<>(Arrays.asList(value));
        Function<Long, Integer> function7 = value -> value.intValue();
        // function8 是function6调用compose组合function5
        // function6是String->List<String>, function5是Integer->String, 所以组合之后,Function8是Integer->List<String>
        Function<Integer, List<String>> function8 = function6.compose(function5);
        // function9 是function7调用andThen方法组合function5
        // function7是Long->Integer, function5是Integer->String, 所以组合之后,Function9是Long->String
        Function<Long, String> function9 = function7.andThen(function5);
        // 输出: [Hello World 1]
        System.out.println(function8.apply(1));
        // 输出: Hello World 100
        System.out.println(function9.apply(100L));
     }

Stream中使用举例

Funtion接口大量被用于集合和流中, 下面就简单举一个例子, 看下Function在Stream中的应用
场景 :

  • 遍历一个List, 将其中小写字母都转换成大写字母进行输出
  • Function 接口的实现负责将小写转换成大写, 代码如下:
        List<String> list = new ArrayList<>(Arrays.asList("biluo", "huangquan", "hongchen", "zimo"));
        Function<String, String> function = item -> item.toUpperCase();
        list.stream().map(function).forEach(item -> System.out.println(item));

输出 :

BILUO
HUANGQUAN
HONGCHEN
ZIMO

更多的用法, 需要进一步了解一下Stream了, 这里只是简单举个栗子

BiFunction接口

  • JDK8新增函数式接口
  • 可以理解为Function的一种扩展, Function接口接收一个参数, 返回一个参数; BiFunction接口接受两个参数, 返回一个参数
  • 唯一的抽象方法apply, 接收两个参数, 返回一个参数
  • 存在一个默认方法addThen, 由于apply方法接收两个参数, 所以不存在compose方法
  • 和Function一样, 在集合与Stream流中均有应用

apply 方法

    /**
     * 输入两个参数, 类型分别是T和U, 返回一个结果, 类型为R
     * @param t 函数第一个输入参数
     * @param u 第二个输入参数
     * @return 返回结果
     */
    R apply(T t, U u);

andThen 方法

/**
 * 传入一个Function类型,该Function类型输入参数为R, 返回结果类型为V
 * 当前BiFunction的apply函数输入参数类型为T, U; 返回结果类型为R
 * 将两个参数组合之后返回一个新的BiFunction方法, 输入参数是T,U,返回结果类型为V
 * 简单来说就是当前的BiFunction是(T, U) -> R, 传入的Function是R -> V
 * 所以组合后的新的Function是(T, U) -> V, 即把BiFunction的返回结果作为入参再传入Function中
 */
default <V> BiFunction<T, U, V> andThen(Function<? super R, ? extends V> after) {
    Objects.requireNonNull(after);
    return (T t, U u) -> after.apply(apply(t, u));
}

BiFunction没有Compose方法是因为BiFunction的apply方法要接收两个参数, 而不管是Function还是BiFunction乃至所有的Java方法, 返回结果都只有一个

API代码样例

    public static void main(String[] args) {
        BiFunction<Integer, Integer, Integer> biFunction = (num1, num2) -> num1 + num2;
        // 输出 : 5
        System.out.println(biFunction.apply(2, 3));
        Function<Integer,Integer> function = num -> num * num;
        // newBiFunction的apply(num1, num2)方法等于function.apply(biFunction(num1, num2))
        BiFunction<Integer, Integer, Integer> newBiFunction = biFunction.andThen(function);
        // 输出 : 25
        System.out.println(newBiFunction.apply(2, 3));

        BiFunction<Integer, Integer, List<Integer>> biFunction2 = (num1, num2) -> new ArrayList<>(Arrays.asList(num1, num2));
        Function<List<Integer>,String> function2 = list -> list.toString();
        BiFunction<Integer, Integer, String> newBiFunction2 = biFunction2.andThen(function2);
        System.out.println(newBiFunction2.apply(1, 2));
    }

集合中使用举例

HashMap中的compute方法接收一个BiFunction类型的参数

        Map<String, String> map = new HashMap<>();
        map.put("name", "qiyexue");
        BiFunction<String, String, String> biFunction = (k, v) -> k + " : " + map.get(k).toUpperCase();
        System.out.println(map.compute("name", biFunction));

输出 :

name : QIYEXUE

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JDK8新特性-Function接口与BiFunction接口 的相关文章

  • Java学习笔记 --- 布尔类型

    一 布尔类型 1 布尔类型也叫boolean类型 boolean类型数据只允许取值true和false 无null public class Bool public static void main String args boolean
  • mac上使用IntelliJ IDEA运行项目

    一 Mac OSX系统下安装Tomcat 1 下载Tomcat官方下载地址 2 解压Tomcat到目录 Library 中 并把文件夹名由 apache tomcat 6 0 16 改为 Tomcat 3 打开 应用程序 Applicati
  • 字符“&”在XML文件中需要被转义

    今天弄Mybatis的配置文件时 因为这样一条语句
  • 剑指offer第二版面试题39:数组中出现次数超过一半的数字(java)

    题目描述 数组中有一个数字出现的次数超过数组长度的一半 请找出这个数字 例子说明 如输入一个长度为9的数组 1 2 3 2 2 2 5 4 2 由于数字2在数组中出现了5次 超过数组长度的一半 因此输出2 分析思路1 基于Partition
  • 对象数组题目 Student类

    package object oriented02 对象数组题目 定义类的Student 包含三个属性 学号为number 年级为state int 成绩为score int 创建20个学生对象 学号为1到20 年级和成绩都是随机产生 问题
  • 【java基础】 方法,实参和形参,方法的重载,签名,递归

    目录 方法概念及使用 实参和形参的关系 重要 方法的重载 方法签名 简单了解 递归 简单介绍 方法概念及使用 方法就是一个代码片段 类似于 C 语言中的 函数 作用 是能够模块化的组织代码 当代码规模比较复杂的时候 做到代码被重复使用 一份
  • JAVA获取类的类对象的三种方式

    自定义一个类 MyClass 并声明该类的对象 class MyClass MyClass mClass1 new MyClass 1 2 3 在上面说过 Class 类的构造方法是私有的 只有 java 虚拟机可以调用该方法创建该类的对象
  • MQ的基本原理是怎样的?MQ的优点有哪些?MQ的核心概念包括哪些?MQ的消息传递模式有哪些?

    1 MQ的基本原理是怎样的 MQ 消息队列 是一种面向消息的中间件 用于实现不同系统之间的异步通信 其基本原理如下 生产者 Producer 将消息发送到消息队列中 而不是直接发送给消费者 Consumer 消息队列将接收到的消息存储在内部
  • javaSE进阶1之static用法

    JavaSE进阶 静态关键字 static static关键字的作用 成员变量分类 静态成员变量 实例成员变量 static修饰成员变量内存原理 static 修饰成员方法的基本用法 成员方法的分类 static修饰成员方法内存原理 sta
  • 一文彻底弄懂零拷贝原理

    零拷贝 零拷贝 Zero Copy 是一种 I O 操作优化技术 可以快速高效地将数据从文件系统移动到网络接口 而不需要将其从内核空间复制到用户空间 其在 FTP 或者 HTTP 等协议中可以显著地提升性能 但是需要注意的是 并不是所有的操
  • 进制及进制转换详解。原码、反码、移码,补码区别介绍。(通俗易懂)

    目录 前言 一 十进制 n进制 进制转换详解 1 先说说什么是进制 2 二进制介绍 3 十进制 n进制 进制转换详解 重点 十进制 gt n进制 2 8 16 n进制 2 8 16 gt 十进制 非十进制间的互相转化 二 原码 反码 移码
  • POI解析word\pdf中表格

  • 解释执行与编译执行语言有什么区别?

    一 主体不同 1 编译执行 由编译程序将目标代码一次性编译成目标程序 再由机器运行目标程序 2 解释执行 将源语言直接作为源程序输入 解释执行 解释一句后就提交计算机执行一句 并不形成目标程序 二 优势不同 1 编译执行 相比解释执行编译执
  • FastJson 之 List<Map>转化成对应List<Object>

    List
  • 求一个数组的最大值最小值及其下标

    求一个数组的最大值最小值及其下标 思路 假定一个数为最大值 如果有个数比假定的最大值还大 那么该数就为最大值 最小值同理 使用for循环 public class MaxMin public static void main String
  • Java对象的快速复制的几种方式

    浅拷贝 深度复制 BeanUtils copyProperties 对象的克隆是指创建一个新的对象 且新的对象的状态与原始对象的状态相同 当对克隆的新对象进行修改时 不会影响原始对象的状态 注释 clone 是object类的protect
  • SM2加解密、签名验签

    导论 SM2是国家密码管理局于2010年12月17日发布的椭圆曲线公钥密码算法 在我们国家商用密码体系中被用来替换RSA算法 国产SM2算法 是基于ECC的 但二者在签名验签 加密解密过程中或许有些许区别 目前鄙人还不太清楚 后期有机会的话
  • IDEA 编写JDBC 第一个示例

    知心惟有雕梁燕 自来相伴 东风不管琵琶怨 落花吹遍 一 新建一个Module 二 在此Module下新建一个包 在包再建一个包 命名为lib 三 导入mysql驱动 四 将mysql驱动添加到项目的库里 五 代码实现 package Con
  • java动态代理简单实例

    java动态代理简单实例 package hello import java lang reflect InvocationHandler import java lang reflect Method import java lang r
  • Java处理SSH-免密登录

    前提 需要测试主机之间能够免密 配置ssh请自行百度 jar包 旧版 com jcraft jsch 仅支持老版的密钥格式 旧版本 RSA

随机推荐

  • 编译支付宝小程序 设置页面滚动时 overflow-y: auto不生效

    前言 由于公司业务调整 特意学习下uni项目框架 其实根据官方api就是实现很多功能 其实都是一些小坑 uni编译支付宝小程序 设置页面滚动时 overflow y auto不生效 解决 设置页面滚动时 不能设置overflow y aut
  • JavaScript教程-对象,文本和属性,方括号,计算属性,属性名称限制,in操作符,for..in,对象引用复制,深层克隆const修改

    对象 正如我们在 数据类型 一章学到的 JavaScript 中有八种数据类型 有七种原始类型 因为它们的值只包含一种东西 字符串 数字或者其他 相反 对象则用来存储键值对和更复杂的实体 在 JavaScript 中 对象几乎渗透到了这门编
  • 选择CentOS还是Ubuntu?

    Ubuntu和CentOS都是常见的Linux发行版 它们都有其优点和适用场景 Ubuntu是一种易于使用的操作系统 适合初学者 它具有良好的社区支持和广泛的软件库 因此很容易找到和安装需要的软件 Ubuntu还经常更新软件包 提供新功能和
  • UTXO介绍

    什么是UTXO 在比特币钱包当中 我们通常能够看到账户余额 然而在中本聪设计的比特币系统中 并没有余额这个概念 比特币余额 是由比特币钱包应用派生出来的产物 中本聪发明了UTXO交易模型 并将其应用到比特币当中 UTXO Unspent T
  • 怎样在html中写css样式,hbuilder的css怎么写

    HBuilder怎么查框架的css的属性 HBuilder在用框架时怎么查框架的css的属性 1 js中定义的变量和函数 在引用变量或函数时 可以跳转到定义的位置 包括HTML中同文件内部跳转及HTML向js文件的跳转 2 css中定义的样
  • Java开发工具JDK+IDEA+MySql+maven+tomact+sqlyong+postMan+redis+RMQ+node

    开发工具 JDK 1 8 含1 8中文API 链接 https pan baidu com s 1t43L4nxCqzmCIhKp JZvIg 提取码 9woy 开发工具 IDEA 含解密文档 链接 https pan baidu com
  • Unity普通项目升级为URP通用渲染管线(图文详解)

    Unity普通项目升级为URP通用渲染管线 前言 一 导入Universal RP 二 创建Pipeline Asset 三 设置Graphics 四 更改Rendering 五 素材升级URP 总结 版权声明 前言 我的unity版本是2
  • RASP解决Java安全问题探讨

    Java 语言在应用场景下有更健全的性能 对于很多企业而言是应用程序编写选择中的 Plan A 树大招风 这也使得它成为攻击者重点关注的对象 在软件开发的过程中 程序员通常会引入第三方库提高自己的研发效率 但开源代码的安全性和可靠性很难保证
  • 租用Topaz Video Enhance AI

    智星云算力平台已认证帐号在智星云租赁并使用Topaz Video Enhance AI 1 租用win10渲染镜像 2 设备管理器 查看显卡状态 3 安装 Topaz Video Enhance AI 软件 4 在 preferences
  • ATM(异步传输模式)是什么?

    异步传输模式 ATM 也称为信元中继 在固定大小的信元中传输数据 通过光纤或双绞线电缆 高速交换 在OSI模型的数据链路层 第2层 运行基于ITU T宽带综合业务数字网络 B ISDN 标准的网络技术 该标准是电信业开发的 自动取款机可以同
  • 【区块链论文整理】SIGMOD 篇 (二)

    SIGMOD Special Interest Group On Management Of Data 是数据库三大顶会之一 近几年也发表了不少水平很高的文章 本文主要针对SIGMOD会议中区块链相关的论文进行简单整理 ACM SIGMOD
  • 运算符之 --- 取余运算 %

    取模运算 javascript取模运算是一个表达式的值除以另一个表达式的值 并返回余数 取模在js里就是取余数的意思 a b 是求余数 a b 是求商 Math abs x 是求x的绝对值 12除以5 2 余数是2 即5 2 2 12 所以
  • C++:使用private继承

    在通常的程序设计中很少使用private继承 因为private继承其实相当于 根据某物实现 而这种情况应该通过类成员变量的方式来实现 那么private继承其实只有两个使用场景 1 需要重写虚函数 include
  • MobileSAM:更快的分割一切!面向移动端的轻量级SAM,比FastSAM快4倍!

    点击下方卡片 关注 CVer 公众号 AI CV重磅干货 第一时间送达 点击进入 gt 图像分割和Transformer 交流群 转载自 极市平台 作者 happy 导读 本文提出一种 解耦蒸馏 方案对SAM的ViT H解码器进行蒸馏 同时
  • 从Inception v1,v2,v3,v4,RexNeXt到Xception再到MobileNets,ShuffleNet,MobileNetV2,ShuffleNetV2,MobileNetV3

    v1 Going deeper with convolutions Inception v1的网络 主要提出了Inceptionmodule结构 1 1 3 3 5 5的conv和3 3的pooling组合在一起 最大的亮点就是从NIN N
  • Dart编程语言概览

    Dart编程语言概览 一个简单的Dart程序 注释 单行 多行 数据类型 字面量 输出方式 字符串插值 main 函数 特定的顶级函数 定义变量var 通过这种方式定义变量不需要指定变量类型 定义一个函数 printInteger int
  • 关于RocketMQ的启动时遇到的一些问题及解决方法

    对于RocketMQ的启动需要配置java环境 所以我们需要在linux上下载jdk 并配置JAVA HOME 配置java环境时遇到的文件不能编辑的问题 我们可以看到该文件对于我们来说是只读权限 所以我们需要提升权限用sudo编辑该文件
  • 特征工程系列:GBDT特征构造以及聚类特征构造

    特征工程系列 GBDT特征构造以及聚类特征构造 本文为数据茶水间群友原创 经授权在本公众号发表 关于作者 JunLiang 一个热爱挖掘的数据从业者 勤学好问 动手达人 期待与大家一起交流探讨机器学习相关内容 0x00 前言 数据和特征决定
  • 面试前看过这篇文章就好了

    一 java基础面试 1 1面向对象和面向过程的区别 面向过程 优点 性能比面向对象高 因为类调用时需要实例化 开销比较大 比较消耗 资源 应用场景 单片机 嵌入式开发 Linux Unix 缺点 没有面向对象易维护 易复用 易扩展 面向对
  • JDK8新特性-Function接口与BiFunction接口

    Function 接口 JDK8新增的函数式接口 接口只有一个抽象方法apply 接受一个T类型参数 返回一个R类型参数 T R表示泛型 可以相同 除了一个抽象的apply方法之外 Function存在两个默认的default方法 comp