151. Java Lambda 表达式 - 使用 Consumer 接口处理对象

151. Java Lambda 表达式 - 使用 Consumer<T> 接口处理对象

Java 中,Consumer<T> 是一个非常重要的功能接口,它接受一个输入参数,但不返回任何结果。与 Supplier<T>(它不接受参数,返回结果)不同,Consumer<T> 专注于对传入的对象执行操作,而不关心返回值。

Consumer<T> 接口的定义

Consumer<T> 接口只有一个抽象方法 accept(T t),用于接受一个类型为 T 的参数并进行处理:

java 复制代码
@FunctionalInterface
public interface Consumer<T> {
    void accept(T t);
}
示例:使用 Consumer<String> 打印字符串
java 复制代码
Consumer<String> printer = s -> System.out.println(s);

这个 Consumer 实现接收一个字符串并将其打印到控制台。可以像这样使用它:

java 复制代码
for (int i = 0; i < 5; i++) {
    int nextRandom = newRandom.getAsInt();
    printer.accept("next random = " + nextRandom);
}

在这个示例中,我们使用 printer 来打印每次生成的随机数。

使用专用的 Consumer

Consumer<T> 接口的实现是通用的,但有时候我们需要处理原始类型数据(例如 intlongdouble),这时装箱(autoboxing)和拆箱(unboxing)会带来性能开销。为了优化性能,JDK 提供了专门的 Consumer 接口处理原始类型:IntConsumerLongConsumerDoubleConsumer

示例:使用 IntConsumer 打印整数
java 复制代码
Consumer<Integer> printer = i -> System.out.println(i);

这段代码使用 Consumer<Integer> 打印整数,但是,如果处理的是大量数据,自动装箱和拆箱可能会影响性能。因此,可以使用专用的 IntConsumer 接口来避免这种性能损失。

java 复制代码
IntConsumer intPrinter = i -> System.out.println(i);

IntConsumeraccept() 方法直接接受 int 类型,而不会进行装箱,因此效率更高。

使用 BiConsumer<T, U> 处理两个参数

除了接受单个参数的 Consumer<T>JDK 还提供了 BiConsumer<T, U> 接口,它可以同时接受两个参数,并对它们进行操作。它的定义如下:

java 复制代码
@FunctionalInterface
public interface BiConsumer<T, U> {
    void accept(T t, U u);
}
示例:使用 BiConsumer<Random, Integer> 打印多个随机数
java 复制代码
BiConsumer<Random, Integer> randomNumberPrinter = (random, number) -> {
    for (int i = 0; i < number; i++) {
        System.out.println("next random = " + random.nextInt());
    }
};

在上面的代码中,randomNumberPrinter 是一个 BiConsumer,它接受一个 Random 对象和一个整数 number,并打印出 number 个随机数。

调用这个 BiConsumer

java 复制代码
randomNumberPrinter.accept(new Random(314L), 5);

输出示例:

java 复制代码
next random = 1
next random = 5
next random = 3
next random = 0
next random = 2

专用的 BiConsumer 接口

Consumer<T> 类似,BiConsumer<T, U> 也有专门的版本,处理原始类型数据,避免装箱和拆箱的开销。它们包括:

  • ObjIntConsumer<T>:接受一个对象和一个 int
  • ObjLongConsumer<T>:接受一个对象和一个 long
  • ObjDoubleConsumer<T>:接受一个对象和一个 double

这些专用接口与 BiConsumer 的工作方式相同,但它们通过避免不必要的装箱来提高性能。

Consumer 传递给 Iterable

Iterable 接口的 forEach() 方法是另一个与 Consumer<T> 紧密结合的地方。forEach() 方法接受一个 Consumer<T> 并对 Iterable 中的每个元素执行操作。这使得对集合的处理更加简洁和高效。

示例:使用 forEach() 遍历列表并打印元素
java 复制代码
List<String> strings = List.of("Java", "Lambda", "Consumer");
Consumer<String> printer = s -> System.out.println(s);
strings.forEach(printer);

在这个例子中,strings.forEach(printer) 会遍历列表 strings,并将 printer Consumer 应用于每个元素,将其打印出来。

输出示例:
java 复制代码
Java
Lambda
Consumer

forEach() 方法提供了一种简单的方式来处理 Iterable 中的每个元素。不再需要手动编写循环语句,代码更加简洁和易于理解。

总结

  • Consumer<T> 接口Consumer<T> 接口用于接受一个对象并对其执行操作,但不返回任何值。它通常用于打印、修改或消费数据。
  • 专用 Consumer 接口 :为了避免装箱和拆箱带来的性能损失,JDK 提供了专用的 IntConsumerLongConsumerDoubleConsumer 接口处理原始类型。
  • BiConsumer<T, U> 接口BiConsumer 接口允许同时处理两个参数,并执行操作。它在需要处理两个输入时非常有用。
  • forEach() 方法forEach() 方法与 Consumer<T> 接口结合使用,提供了一种简单的方式来遍历 Iterable 并对每个元素执行操作。

通过理解并使用这些接口,可以在 Java 中编写更简洁、易读且高效的代码。

相关推荐
想用offer打牌9 小时前
MCP (Model Context Protocol) 技术理解 - 第二篇
后端·aigc·mcp
崔庆才丨静觅9 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby606110 小时前
完成前端时间处理的另一块版图
前端·github·web components
KYGALYX10 小时前
服务异步通信
开发语言·后端·微服务·ruby
掘了10 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅10 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅10 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
爬山算法11 小时前
Hibernate(90)如何在故障注入测试中使用Hibernate?
java·后端·hibernate
崔庆才丨静觅11 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment11 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端