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 中编写更简洁、易读且高效的代码。

相关推荐
RainbowSea1 分钟前
Windows 安装 RabbitMQ 消息队列超详细步骤(附加详细操作截屏)
后端
RainbowSea2 分钟前
Windows 11家庭版安装 Docker
后端
_码农121383 分钟前
Spring IoC容器与Bean管理
java·后端·spring
哈基咩14 分钟前
Go 语言模糊测试 (Fuzz Testing) 深度解析与实践
开发语言·后端·golang
mCell15 分钟前
告别轮询!深度剖析 WebSocket:全双工实时通信原理与实战
后端·websocket·http
素界UI设计35 分钟前
开源网页生态掘金:从Bootstrap二次开发到行业专属组件库的技术变现
前端·开源·bootstrap
潘小安36 分钟前
【译】六个开发高手使用的 css 动画秘诀
前端·css·性能优化
前端开发爱好者1 小时前
尤雨溪官宣:Vite 历史性的一刻!超越 Webpack!
前端·javascript·vite
ClouGence1 小时前
从达梦到 StarRocks:国产数据库实时入仓实践
数据库·后端
前端开发爱好者1 小时前
Vue3 "抛弃" Axios !用上了 专属请求库!
前端·javascript·vue.js