BiConsumer 是 Java 8 提供的函数式接口,用于接收两个参数并执行无返回值的操作,典型应用包括遍历 Map 键值对、组合消费逻辑(andThen)及避免常见坑如空指针和不可变对象修改。

BiConsumer 是 Java 8 引入的函数式接口,专为“接收两个参数、只做操作、不返回结果”的场景设计。它不计算值,而是执行副作用——比如打印、修改对象、更新数据库、记录日志或触发校验。
核心用法:用 Lambda 快速定义消费逻辑
声明一个 BiConsumer,只需指定两个泛型类型(可以相同,也可以不同),然后用 Lambda 写处理逻辑:
-
语法简洁:
BiConsumer<String, Integer> printer = (s, i) -> System.out.println(s + " → " + i); -
执行调用:直接调用
accept()方法传入两个实参:printer.accept("订单号", 1001); -
无返回、不可省略分号:Lambda 体里不能写
return,也不能漏掉分号(除非是方法体单语句且无大括号)
典型场景:遍历 Map 的键值对
Map 接口原生支持 forEach(BiConsumer),这是最自然、最高效的用法:
- 避免手动取
entrySet()或写 for-each 循环 - 无需解构
Map.Entry,直接拿到key和value - 示例:
map.forEach((k, v) -> System.out.println(k + "=" + v)); - 也可用方法引用:
map.forEach(this::logEntry);(前提是logEntry(String, Object)存在且签名匹配)
进阶技巧:组合多个操作(andThen)
当需要按顺序执行两步消费动作(比如先校验、再记录),可用 andThen() 链式拼接:
立即学习“Java免费学习笔记(深入)”;
BiConsumer<String, Integer> validator = (k, v) -> { if (v < 0) throw new IllegalArgumentException(); };BiConsumer<String, Integer> logger = (k, v) -> System.out.println("Saved: " + k + "=" + v);BiConsumer<String, Integer> combined = validator.andThen(logger);- 调用
combined.accept("score", 95)会先校验、再打印;若传 -1,则在校验阶段抛异常,logger 不执行
实用提醒:别踩这些常见坑
- 不能中断遍历:BiConsumer 本身不支持 break 或 return 跳出循环,如需条件过滤,请改用 Stream.filter() + forEach
-
参数可变性依赖实际类型:如果传入的是不可变对象(如 String、Integer),
accept里无法修改其值;要改状态,得传可变对象(如自定义类、StringBuilder、数组) -
空指针风险需主动防御:Lambda 体内建议加
Objects.requireNonNull(t)或判空,尤其在生产环境处理外部输入时 - 不要把它当工具方法容器:它不是用来封装业务计算逻辑的,真正复杂的处理(如支付验签、状态比对)应拆到独立 service 方法中,BiConsumer 只负责调度和衔接


















