Java8之Function函数、BiFunction函数详解

众所周知,Java8提供了一下非常重要的函数式接口。今天我们就来讲讲其中一个函数式接口-----Function接口。
下面的代码就是Function接口的全部代码。接下来我们逐个分析一下。

@FunctionalInterface
public interface Function<T, R>

@FunctionalInterface 表明该接口是一个函数式接口
<T, R> T 代表参数,R 代表返回值。

第一个方法------R apply(T t)

示例代码:

public class FunctionTest {public static void main(String[] args) {FunctionTest functionTest = new FunctionTest();System.out.println(functionTest.compute(1, value -> 2 * value));}public int compute(int a, Function<Integer, Integer> function) {int result = function.apply(a);return result;}
}

上述代码展示的就是Function接口中apply方法的使用,其中通过 functionTest.compute方法将两个参数传过去,在compute方法中,function使用参数进行运算。

第二个方法 ------- compose

这个方法是一个默认方法。为了方便在接口中实现具体逻辑,而添加的关键字。
我们可以看到compose方法有一个输入参数为Function类型的值,并且也会返回一个Function类型的值,重点我们看最后一句就会发现,它是先调用参数的apply 方法 再调用调用者的apply 方法

default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {Objects.requireNonNull(before);return (V v) -> apply(before.apply(v));}

通过上面的分析,可以得出结果----12,即对参数先执行 value * value,在执行 value * 3。

System.out.println(functionTest2.compute(2, value -> value * 3, value -> value * value));public int compute(int a, Function<Integer, Integer> function1, Function<Integer, Integer> function2) {return function1.compose(function2).apply(a);}

第三个方法 ------ andThen

大家是不是觉得这个方法和上面的compose方法差不多,唯一的差别就是最后一句。该方法执行的顺序就是先执行调用者的apply方法,在执行参数的apply方法。(与compose方法相反)

default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {Objects.requireNonNull(after);return (T t) -> after.apply(apply(t));}

示例代码
经过上面的分析,我们很容易得出结果,值为36。

System.out.println(functionTest2.compute(2, value -> value * 3, value -> value * value));public int compute2(int a, Function<Integer, Integer> function1, Function<Integer, Integer> function2) {return function1.andThen(function2).apply(a);}

第四个方法 ------ identity

static <T> Function<T, T> identity() {return t -> t;}

该行代码因为实现了Function中唯一的抽象方法,所以通过下面这行代码实例化出了一个 “接口” 对象,同样也会输出helloworld

Function<String, String> fun1 = Function.identity();String str1 = fun1.apply("helloWorld");System.out.println(str1);

看完了Function,相信大家在学习Java8的时候,都看到了还有一个叫BiFunction的类,下面我们来分析一下BiFunction

什么是BiFunction

@FunctionalInterface
public interface BiFunction<T, U, R>

它也是一个函数式接口,它是Function 的 另一种形式,它接收两个参数(T,U),返回一个参数(R)。那么接下来我们看看这个接口里面有哪些方法吧。

第一个方法 ------ apply

R apply(T t, U u);

示例代码:

System.out.println(functionTest2.compute4(2, 3, (value1, value2) -> value1 + value2));public int compute4(int a, int b, BiFunction<Integer, Integer, Integer> biFunction) {return biFunction.apply(a, b);}

上述代码,使用的就是apply方法,我们发现,其实它跟Function里面的apply其实一样,也就是多了一个参数而已。接下来,我们看第二个方法。

第二个方法 ----- andThen

源码:

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));}

我们发现,andThen方法里面的参数是Function类型的,那为什么不能是BiFunction类型的呢。
andThen是先执行调用者的apply,也就是说他先调用BiFunction的apply方法,再去调用参数的apply方法;其中根据Java的规范,一个方法,只能有一个返回值。所以当执行参数的apply方法的时候,只能有一个参数,所以andThen方法里面的参数必须是Function类型的。

那么大家可能会问了,为什么BiFunction里面没有compose方法。
根据Function接口里面的compose方法,我们可以分析出,它是先执行参数的apply方法,在执行调用者的apply方法。
假如BiFunction里面有compose,又因为BiFunction接受两个参数,那么通过上面的分析,可以得出,它的compose方法的参数必定是BiFunction类型的,但是下一步执行调用者的apply方法的时候,因为只有一个参数,所以是无法满足的。所以BiFunction里面没有compose方法。



源码:

public interface Function<T, R> {/*** 将此函数应用于给定参数* 真正执行函数接口的方法*/R apply(T t);/*** 函数链,before执行的结果做根函数为参数*/default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {Objects.requireNonNull(before);return (V v) -> apply(before.apply(v));}/*** 函数链,根函数执行结果做为after的参数*/default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {Objects.requireNonNull(after);return (T t) -> after.apply(apply(t));}/*** 返回一个参数做为返回值的函数*/static <T> Function<T, T> identity() {return t -> t;}
}

看注释有些绕,还是看例子

//例1
public class FunctionDemo {public static void main(String[] args) {Function<Integer,Integer> root = (v) -> {System.out.println("root apply");return v + 1;// 12};Function<Integer,Integer> before = (v) -> {System.out.println("before apply");return v + 1;// 先得结果11,再传给root};System.out.println(root.compose(before).apply(10));// before apply// root apply// 12}
}
//例2
public class FunctionDemo {public static void main(String[] args) {Function<Integer,Integer> root = (v) -> {System.out.println("root apply");return v + 1;// 先得结果11,再传给after};Function<Integer,Integer> after = (v) -> {System.out.println("after apply");return v + 1;// 12};System.out.println(root.andThen(after).apply(10));// root apply// after apply// 12}
}

例1和例2虽然参数一样,结果一样,但是相对与根函数root执行的顺序一个在前,一个在后。

Function与Consumer接口都有andThen方法,两者的区别是对参数的使用方式不同。每Consumer使用的是同一个原始参数,Function的参数只会被根函数使用一次,之后的函数使用的是前一个函数的结果做为参数。

了解了Function,其他的也就一目了然了:

BiFunction<T,U,R>:代表了一个接受两个输入参数的方法,并且返回一个结果DoubleFunction<R>:代表接受一个double值参数的方法,并且返回结果DoubleToIntFunction:接受一个double类型输入,返回一个int类型结果。DoubleToLongFunction:接受一个double类型输入,返回一个long类型结果IntFunction<R>:接受一个int类型输入参数,返回一个结果 。IntToDoubleFunction:接受一个int类型输入,返回一个double类型结果 。IntToLongFunction:接受一个int类型输入,返回一个long类型结果。LongFunction<R>: 接受一个long类型输入参数,返回一个结果。LongToDoubleFunction: 接受一个long类型输入,返回一个double类型结果。LongToIntFunction:接受一个long类型输入,返回一个int类型结果。ToDoubleBiFunction<T,U>:接受两个输入参数,返回一个double类型结果ToDoubleFunction<T>:接受一个输入参数,返回一个double类型结果ToIntBiFunction<T,U>:接受两个输入参数,返回一个int类型结果。ToIntFunction<T>:接受一个输入参数,返回一个int类型结果。ToLongBiFunction<T,U>:接受两个输入参数,返回一个long类型结果。ToLongFunction<T>:接受一个输入参数,返回一个long类型结果。

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

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

相关文章

告诉你win10自带录屏怎么使用

win10自带录屏怎么使用呢一些游戏玩家之前都是下载第三方屏幕录像软件录像&#xff0c;升级win10过后发现win10系统自带录屏功能&#xff0c;但是又不知道在哪打开?针对这个问题&#xff0c;我给大家带来了详细的操作步骤&#xff0c;一起来看看吧 不得不说win10系统实在是太…

Content-Type详解SpringBoot中如何根据Content-Type解析数据

文章目录Content-Type详解Content-Type是什么&#xff1f;Content-Type的格式Post请求中常见的Content-Type类型的结构SpringBoot中如何根据Content-Type解析数据一、接收get请求二、接收Post请求总结&#xff1a;Content-Type详解 Content-Type是什么&#xff1f; 在HTTP协议…

云骑士u盘装win8系统教程

云骑士u盘装win8系统教程 第一步 先在浏览器搜索云骑士官网&#xff1a;www.yunqishi.net 在官网上下载云骑士装机大师软件&#xff0c;下载好以后打开云骑士装机大师&#xff0c;打开后云骑士会自动配置用户的电脑信息&#xff0c;选择启动U盘界面。并且在电脑上插入U盘。 第…

U盘重装win7系统教程

第一步 先在浏览器搜索云骑士官网&#xff1a;www.yunqishi.net 在官网上下载云骑士装机大师软件&#xff0c;下载好以后打开云骑士装机大师&#xff0c;打开后云骑士会自动配置用户的电脑信息&#xff0c;选择启动U盘界面。并且在电脑上插入U盘。 2 第二步 接着就进入了选择系…

【编程技巧】Stream流之list转map、分组取每组第一条

前言 JDK1.8推出的stream流能极大的简化对集合的操作&#xff0c;让代码更美观&#xff0c;老规矩&#xff0c;直接上代码。 一、list转map 取list中对象的某个属性作为唯一key&#xff0c;对象作为value形成一个map集合&#xff0c;能够便于在后续业务中取值而不用遍历list…

番茄花园 Win10 系统 64位 全新纯净版 v2021.01

番茄花园 Win10 系统 64位 全新纯净版 v2021.01介绍&#xff1a; 1、支持IDE、SATA光驱启动恢复安装&#xff0c;支持WINDOWS下安装&#xff0c;支持PE下安装; 2、自动安装 AMD/Intel 双核 CPU 驱动和优化程序&#xff0c;发挥新平台的最大性能; 3、安装方便快速&#xff0c…

Java中String类常用方法详解: concat(),format(),charAt(),indexOf(),substring(),compareTo(),split(),replaceAll

文章目录1.连接字符串 concat()2.创建格式化对象 format()3.获取字符串某一位置字符 charAt()4.获取字符串的长度 length()5.查找子串在字符串中的位置 indexOf()6.截取字符串的子串 substring()7.字符串比较 compareTo()8.字符串大小写转换 toLowerCase()【大写换小写】 toUpp…

技术编辑帮你win7系统查看显卡容量大小的详细技巧

技术帮你win7系统查看显卡容量大小的详细技巧

索尼首次展示其Airpeak电影摄制无人机

索尼首次展示其Airpeak电影摄制无人机 在模糊的新闻稿和同样神秘的视频中宣布Airpeak仅仅两个月后&#xff0c;索尼就在虚拟CES 2021演示中展示了其新无人机。Airpeak支持Sony的Alpha系列无反光镜相机&#xff0c;并使用AI在飞过天空时保持图像稳定。 索尼首次展示其Airpeak电…

Guava中基础工具类Joiner的使用字符串拼接方法 joiner.on

Guava 中有一些基础的工具类&#xff0c;如下所列&#xff1a; 1&#xff0c;Joiner 类&#xff1a;根据给定的分隔符把字符串连接到一起。MapJoiner 执行相同的操作&#xff0c;但是针对 Map 的 key 和 value。 2&#xff0c;Splitter 类&#xff1a;与 Joiner 操作相反的类…

开机按f12怎么恢复系统 开机按f12恢复系统

有时候我们可能会遇到系统损坏或者是系统崩溃的问题,都会开不了机.那么开机按f12怎么恢复系统呢?用户并不知道如何操作,相信用户都很感兴趣该问题的解决方法,下面我在win7纯净版找到关于开机按f12恢复系统的详细操作教程,需要的朋友可以参考一下. 开机按f12怎么恢复系统 1.重启…

手把手教你dns服务器未响应导致无法上网怎么办

dns服务器未响应怎么办&#xff1f;其实每个问题都是有着相对应的原因外加解决方法的&#xff0c;我这刚好就有一篇关于如何解决dns服务器未响应的方法&#xff0c;现在就来分享给各位小伙伴们哈~ 不知道小伙伴们在使用电脑进行上网的时候&#xff0c;有木有遇到过这样子的一个…

Java 常用日志框架介绍

一、日志简介 1.1 日志是什么&#xff08;WHAT&#xff09; 日志&#xff1a;记录程序的运行轨迹&#xff0c;方便查找关键信息&#xff0c;也方便快速定位解决问题。 通常&#xff0c;Java程序员在开发项目时都是依赖Eclipse/IDEA等集成开发工具的Debug 调试功能来跟踪解决Bu…

淘集集收货地址在哪改 淘集集添加收货地址方法

淘集集app上购物方便且便宜&#xff0c;所以很多人都在使用。但有些人不知道该如何添加和修改收货地址。所以为大家详细介绍下方法。 淘集集收货地址在哪改 淘集集添加收货地址方法   淘集集收获地址在哪改   1、由于购物下单之前必须填写收货地址&#xff0c;因此有需要的…

Java中记录日志方式比较及相关建议

一、记录日志的几种方式比较 为了测试&#xff0c;我在测试类中写了七种打印方式&#xff0c;分别如下&#xff1a; Slf4j RunWith(SpringRunner.class) SpringBootTest public class ErrorLogTest {Testpublic void ss(){try{float xx 1/0;log.info("xx&#xff1a;{}&…

word打字覆盖后面的字 教你word打字覆盖后面的字怎么办

我之所以会知道解决word打字覆盖后面的字这个问题的方法&#xff0c;是因为之前遇到这个情况的时候也不知道该如何处理了&#xff0c;不过幸亏一个朋友告诉了我解决这个问题的办法&#xff0c;然后我就多了解了一下子这方面的知识&#xff0c;所以我现在就将解决这个问题的方法…

Windows7系统资源怎么看?

在平时的工作中&#xff0c;我们会安装很多软件&#xff0c;虽然用完卸载了&#xff0c;但是还是会有残留占用资源&#xff0c;于是我们就得去看一下系统资源&#xff0c;可是很多用户不知道系统资源怎么看&#xff1f;其实方法很简单&#xff0c;如果你不知道Windows7系统资源…

Collectors.collectingAndThen()Collectors.collectingAndThen 去重Stream分组groupBy后取单一字段值、取列表第一个值方式

Collectors.collectingAndThen() Java 8 流的新类 java.util.stream.Collectors 实现了 java.util.stream.Collector 接口&#xff0c;同时又提供了大量的方法对流 ( stream ) 的元素执行 map and reduce 操作&#xff0c;或者统计操作。 Collectors.collectingAndThen() 函数应…

EasyBoot如何使用?EasyBoot制作多系统启动盘教程

在平时的工作中&#xff0c;我们会安装很多软件&#xff0c;虽然用完卸载了&#xff0c;但是还是会有残留占用资源&#xff0c;于是我们就得去看一下系统资源&#xff0c;可是很多用户不知道系统资源怎么看&#xff1f;其实方法很简单&#xff0c;如果你不知道Windows7系统资源…

问题:在使用dubbo 2.5.3之前的版本@Service来发布服务时,当该服务中有@Transactional,是无法正常发布的?

问题&#xff1a;在使用dubbo 2.5.3之前的版本Service来发布服务时&#xff0c;当该服务中有Transactional,是无法正常发布的? 解决方案&#xff1a; 因为事务TransactionManagement默认是使用了jdk的代理即基于接口的代理&#xff0c;必须改成基于类的代理&#xff0c;servi…