BiFunction是Java 8引入的函数式接口,用于两个输入、一个输出的纯计算场景,强调可复用、可传递、可组合,适用于字段联动计算、DTO组装、缓存键构造及Stream合并等业务链路。

BiFunction 是 Java 8 引入的函数式接口,专为“两个输入、一个输出”的纯计算场景设计。它不负责状态变更或副作用,核心价值在于把双参数逻辑封装成可复用、可传递、可组合的单元。
定义和写法要匹配语义
声明时明确三个类型:第一个参数类型(T)、第二个参数类型(U)、返回类型(R)。不要强行塞进类型相同但语义不同的参数——比如“用户ID + 用户名”和“金额 + 折扣率”,类型可能都是 String 或 BigDecimal,但业务含义不同,BiFunction 的泛型正是为此保留区分度。
- 用 Lambda 最直观:BiFunction
builder = (id, age) -> new User(id, age); - 构造器引用也简洁:BiFunction
builder = User::new; (前提是 User 有对应构造方法) - 避免匿名类,除非需在 lambda 外维护复杂状态(这种情况本身已偏离 BiFunction 设计初衷)
用在真实业务链路里
它不是玩具接口,而是解决具体耦合问题的工具。常见落地点包括:
- 字段联动计算:动态表单中,“城市编码 + 行政区划级别” → 返回对应邮编规则对象
- DTO 与配置组装:传入订单 DTO 和促销策略 Map,输出含优惠明细的结算单
- 缓存键构造:用“租户ID + 业务类型”拼出 Redis key,类型安全且可读性强
- Stream 合并逻辑:Collectors.toMap 的 mergeFunction 参数必须是 BiFunction,处理重复 key 时合并 value
执行和组合要稳住边界
调用 apply(t, u) 即可触发计算,但要注意两点:
- null 防御要前置:BiFunction 不声明异常,也不自动判空。关键参数建议用 Objects.requireNonNull(t, "id must not be null") 包一层,而不是在 lambda 里写 if (t == null)
- andThen 用于结果再加工:比如先算实付金额,再转成带千分位的字符串:calculateAmount.andThen(DecimalFormat::format)。注意 andThen 接收的是 Function,不是另一个 BiFunction
别和 BinaryOperator 混用
如果两个参数类型相同、操作满足结合律/交换律(如加、乘、max),优先选 BinaryOperator
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











