三分钟掌握 BiFunction

三分钟掌握 BiFunction

Java中的BiFunction接口是Java 8引入的一个核心函数式接口,用于表示接受两个输入参数生成一个结果的操作。它属于java.util.function包,为Lambda表达式和方法引用提供了更灵活的支持。以下是对BiFunction接口的详细解析:


1. 接口定义

@FunctionalInterface
public interface BiFunction<T, U, R> {R apply(T t, U u); // 核心方法:接受T和U类型参数,返回R类型结果// 组合方法:将当前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));}
}
  • 泛型参数
    • T:第一个输入参数的类型。
    • U:第二个输入参数的类型。
    • R:返回结果的类型。
  • 函数式方法apply(T t, U u) 是唯一的抽象方法。
  • 组合方法andThen 允许将结果传递给另一个Function进行后续处理。

2. 方法的具体工作流程

方法一:R apply(T t, U u);

flowchart LRA[输入参数 T] --> C[BiFunction]B[输入参数 U] --> CC -->|apply 处理| D[结果 R]

方法二:default <V> BiFunction<T, U, V> andThen(Function<? super R, ? extends V> after)

1. 方法签名解析

  • <V>:声明新的泛型类型,表示最终返回结果的类型。
  • BiFunction<T, U, V>:返回一个新的 BiFunction,它接收 TU 参数,最终返回 V 类型。
  • Function<? super R, ? extends V>
    • ? super R:允许 after 函数接收 R 或其父类型(协变性)。
    • ? extends V:允许 after 函数返回 V 或其子类型(逆变性)。
    • 这种设计增强了方法的灵活性(遵循 PECS原则:Producer-Extends, Consumer-Super)。

2. 实现逻辑

Objects.requireNonNull(after);
return (T t, U u) -> after.apply(apply(t, u));
  • 步骤分解
    1. 空指针检查Objects.requireNonNull(after) 防止后续操作因 afternull 而崩溃。
    2. 调用原始 BiFunction:通过 apply(t, u) 得到中间结果(类型 R)。
    3. 传递结果给 after:将中间结果作为输入,调用 after.apply(),得到最终结果(类型 V)。
  • 链式操作:通过组合多个函数,形成 处理流水线

3. 核心特性

(1)函数式编程的核心组件

  • BiFunction 用于将两个值转换为一个新值,是函数组合和链式操作的基础。
  • 与单参数的Function接口不同,BiFunction明确支持双参数操作。

(2)与 BinaryOperator 的关系

  • BinaryOperator<T>BiFunction<T, T, T> 的子接口,专用于两个同类型输入和同类型输出的场景。
    BinaryOperator<Integer> add = (a, b) -> a + b;
    

(3)组合操作(andThen)

  • 场景:计算两个数的平方和后,转换为十六进制字符串。
BiFunction<Integer, Integer, Integer> sumSquares = (a, b) -> a*a + b*b;
Function<Integer, String> toHex = Integer::toHexString;// 组合两个函数
BiFunction<Integer, Integer, String> pipeline = sumSquares.andThen(toHex);String result = pipeline.apply(3, 4); // 3² + 4² = 25 → 0x19 → "19"

执行流程

flowchart LRA[输入 T=3] --> C[sumSquares]B[输入 U=4] --> CC -->|中间结果 R=25| D[toHex]D -->|最终结果 V=19| E[输出]

4. 使用场景

(1)简单运算

BiFunction<Integer, Integer, Integer> add = (a, b) -> a + b;
int sum = add.apply(5, 3); // 结果:8

(2)对象操作
合并两个对象的属性:

BiFunction<String, String, String> concat = (s1, s2) -> s1 + s2;
String fullName = concat.apply("John", "Doe"); // "JohnDoe"

(3)集合处理
在流式操作中合并两个集合:

BiFunction<List<String>, List<String>, List<String>> mergeLists = (list1, list2) -> Stream.concat(list1.stream(), list2.stream()).collect(Collectors.toList());

(4)复杂业务逻辑
例如,根据用户输入和数据库数据生成报告:

BiFunction<UserInput, DatabaseData, Report> generateReport = (input, data) -> new Report(input.filter(data), data.getTimestamp());

5. 注意事项

(1)异常处理

  • apply方法不声明受检异常(checked exceptions),若操作可能抛出异常,需在Lambda内部处理:
    BiFunction<String, String, Integer> safeParse = (s1, s2) -> {try {return Integer.parseInt(s1) + Integer.parseInt(s2);} catch (NumberFormatException e) {return 0;}
    };
    

(2)空安全性

  • 对输入参数进行null检查以避免NullPointerException

(3)性能考量

  • 在性能敏感场景中,避免过度复杂的链式操作(如多层andThen),可能影响可读性和效率。

6. 对比其他接口

接口 输入参数 返回类型 典型用例
Function<T, R> 1 (T) R 单个值的转换,如String::length
BiFunction<T, U, R> 2 (T, U) R 合并两个值,如坐标相加
BinaryOperator<T> 2 (T, T) T 两个同类型操作,如Integer::sum

7. 总结

BiFunction是处理双参数函数式操作的基石,通过applyandThen方法支持灵活的组合逻辑。它在数据转换、集合操作和业务逻辑封装中广泛应用,是Java函数式编程不可或缺的工具之一。理解其特性和使用场景,能够显著提升代码的表达力和简洁性。

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

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

相关文章

蓝绿部署深度解析:从理论到实践的全方位学习指南

一、蓝绿部署的基本概念 (一)定义 蓝绿部署是一种软件发布策略,通过设置两个相同的环境(“蓝色”和“绿色”),最大限度地减少停机并降低与部署新版本应用程序相关的风险。 (二)工作原理 蓝绿部署的核心思想是将应用程序的部署过程分为两个阶段:测试阶段和生产阶段。在…

Elasticsearch 高级

Elasticsearch 高级建议阅读顺序:Elasticsearch 入门 Elasticsearch 搜索 Elasticsearch 搜索高级 Elasticsearch高级(本文)1. nested 类型 1.1 介绍 Elasticsearch 中的 nested 类型允许你在文档内存储复杂的数据结构,比如一个用户可能有多个地址,或者一个博客文章可能有…

mysql日志写马

mysql日志写马 条件 1.全局变量general_log为ON。 mysql有两个全局变量:general_log指的是日志保存状态,值为ON/OFF,general_log_file指的是日志的保存路径。 只有当general_log为ON时,日志才会被记录进去,所以我们要先打开这个全局变量,使用命令查看全局变量状态‘ show…

滚动部署学习指南:从理论到实践,掌握关键技术和流程

一、滚动部署概述 (一)定义 滚动部署是一种逐步更新应用实例的策略,通过逐批次替换旧版本实例来完成版本升级,以减少服务中断时间并降低更新风险。 (二)应用场景 滚动部署适用于需要高可用性和低风险的软件更新场景,例如 Web 应用程序更新、移动应用后端服务更新以及云原…

ctfshow-web入门-爆破(web21-web28)

web21 打开后要求登录附件是一个密码字典使用bp抓包,将抓到的东西进行base64解码发现是admin:密码的键值对添加payload,padload类型为自定义迭代器,位置1为admin:位置2为导入的字典添加base64编码和取消url编码然后开始攻击,发现长度和其他不同的包,查看响应,发现flagweb…

灰度发布学习大纲:从理论到实践,掌握关键技术和流程

一、灰度发布概述 1. 定义与别名灰度发布:一种渐进式的软件发布策略,也被称为金丝雀发布(Canary Release)。 目的:通过逐步向用户群体推送更新,降低新版本引入的潜在风险,提升用户体验,实现不停机的热迁移。2. 灰度发布的优势降低风险:逐步验证新版本的稳定性。 快速反…

代码随心录第三天|Leecode 203.移除链表元素 707.设计链表 206.反转链表

1、Leecode 203.移除链表元素 题目链接:https://leetcode.cn/problems/remove-linked-list-elements/description/ 题目描述:解题思路:移除操作就是让节点next指针直接指向下下一个节点,因为单链表的特殊性,只能指向下一个节点,所以头节点需要单独考虑,这种方法是直接使…

【THM】Linux Privilege Escalation

Linux Privilege Escalation/Linux 权限提升 什么是权限提升 “权限提升”是什么意思? 权限提升通常涉及从较低权限的帐户到较高权限的帐户。 从技术上讲,它是利用操作系统或应用程序中的漏洞、设计缺陷或配置疏忽来获得对通常限制用户访问的资源的未经授权的访问。 权限提升…

kettle从入门到精通 第九十三课 ETL之kettle kettle 调用web service接口5种方法,一文彻底搞懂

场景:群里有小伙伴向我求助如何调用web service接口,趁着周末时间,给兄弟们搞demo。 1、本次使用的web service服务接口地址是http://ws.webxml.com.cn/WebServices/WeatherWS.asmx?op=getSupportCityDataset, 此接口根据用户输入的城市名称可获取城市下属单位,如下图所示…

分享一款替代 GitLab 的开源软件 gogs ,适合中小企业,非常优秀!

这篇文章,分享一款替代 GitLab 的开源软件 gogs ,Github 上有 4 万多颗 star ,笔者认为它非常优秀 ,适合中小企业。1 Gogs 简介 Gogs 是一款极易搭建的自助 Git 服务,它使用 Go 语言开发,只要 Go 语言支持的平台它都支持,包括 Linux 、Mac OS X、Windows 以及 ARM 平台。…

【闲话 No.3】 并查集相关

并查集的复杂度证明及可持久化。命に嫌われている。 小唐话 感觉有的时候已经无法与人正常交流,净做唐事、说些唐话了。或许是我无法准确猜到别人喜欢什么吧。 不过还是自己心底一点 joker 之心/私心作祟吧。 感觉我有时做的唐事真的挺对不起大家的。 可我又怎么战胜心底的那…