Java Consumer 接口
最后修改时间:2025 年 4 月 16 日
java.util.function.Consumer 接口表示一个接受单个输入参数且不返回任何结果的操作。它是一个函数式接口,具有一个抽象方法 accept。Consumer 用于产生副作用的操作,例如打印或修改对象。
Consumer 是 Java 8 中添加的 Java 函数式编程工具的一部分。与大多数函数式接口不同,Consumer 操作旨在产生副作用。该接口提供了用于消费者链的默认方法。
Consumer 接口概述
Consumer 接口包含一个抽象方法和一个默认方法。关键方法 accept 对输入执行操作。andThen 方法启用消费者链。
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
default Consumer<T> andThen(Consumer<? super T> after);
}
上面的代码显示了 Consumer 接口的结构。它使用泛型,其中 T 是输入类型。该接口使用 @FunctionalInterface 注解进行注释,以表明其单抽象方法的性质。
基本 Consumer 用法
使用 Consumer 的最简单方法是使用 lambda 表达式。我们在 accept 方法中定义如何处理输入。示例将字符串打印到控制台。
package com.zetcode;
import java.util.function.Consumer;
public class Main {
public static void main(String[] args) {
// Define a consumer that prints strings
Consumer<String> printer = s -> System.out.println(s);
// Use the consumer
printer.accept("Hello, Consumer!");
// Consumer using method reference
Consumer<String> methodRefPrinter = System.out::println;
methodRefPrinter.accept("Method reference consumer");
}
}
此示例演示了使用 lambda 和方法引用的基本 Consumer 用法。打印机 consumer 接受一个 String 并将其打印出来。方法引用为与 Consumer 签名匹配的现有方法提供了更简洁的语法。
Consumer 与集合
Consumer 经常通过 forEach 方法与集合一起使用。这使得可以在没有显式循环的情况下进行干净的迭代模式。示例处理一个数字列表。
package com.zetcode;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
public class Main {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// Consumer to print numbers with prefix
Consumer<Integer> numberPrinter = n ->
System.out.println("Number: " + n);
// Apply consumer to each element
numbers.forEach(numberPrinter);
// Inline consumer
numbers.forEach(n -> System.out.println(n * 2));
}
}
此示例显示了 Consumer 与集合的用法。我们定义了一个数字打印机 consumer 并将其传递给 forEach。第二个 forEach 演示了一个内联 consumer。这两种方法都处理每个集合元素。
使用 andThen 进行 Consumer 链
andThen 方法允许链接消费者,其中每个消费者按顺序处理相同的输入。这使得可以从简单的消费者创建复杂的处理管道。
package com.zetcode;
import java.util.function.Consumer;
public class Main {
public static void main(String[] args) {
// First consumer logs the message
Consumer<String> logger = s ->
System.out.println("LOG: " + s);
// Second consumer sends email notification
Consumer<String> notifier = s ->
System.out.println("Sending notification: " + s);
// Chain the consumers
Consumer<String> processor = logger.andThen(notifier);
// Process a message
processor.accept("System started successfully");
}
}
此示例显示了使用 andThen 的消费者链。输入消息首先被记录,然后触发一个通知。两个消费者都接收相同的输入。保证执行顺序。
使用 Consumer 修改对象
Consumers 经常用于修改对象状态。由于它们接受参数但不返回任何内容,因此它们非常适合于变异操作。示例更新产品价格。
package com.zetcode;
import java.util.function.Consumer;
class Product {
String name;
double price;
Product(String name, double price) {
this.name = name;
this.price = price;
}
@Override
public String toString() {
return name + ": $" + price;
}
}
public class Main {
public static void main(String[] args) {
Product laptop = new Product("Laptop", 999.99);
// Consumer to apply discount
Consumer<Product> discount = p ->
p.price = p.price * 0.9; // 10% discount
System.out.println("Before: " + laptop);
discount.accept(laptop);
System.out.println("After: " + laptop);
}
}
此示例演示了使用 Consumer 进行对象修改。折扣 consumer 接受一个 Product 并将其价格降低 10%。Consumers 非常适合此类更改状态的操作,同时保持代码清洁。
BiConsumer 接口
虽然 Consumer 接受一个参数,但 BiConsumer 处理两个输入。当操作需要两个参数时,它很有用。示例处理键值对。
package com.zetcode;
import java.util.function.BiConsumer;
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
Map<String, Integer> ages = new HashMap<>();
ages.put("John", 25);
ages.put("Jane", 30);
ages.put("Bob", 35);
// BiConsumer to print key-value pairs
BiConsumer<String, Integer> agePrinter =
(name, age) -> System.out.println(name + " is " + age + " years old");
// Process each map entry
ages.forEach(agePrinter);
// Inline BiConsumer
ages.forEach((k, v) -> System.out.println(k + ": " + v));
}
}
此示例显示了 BiConsumer 的用法。agePrinter 接受 map 键和值。Map 的 forEach 需要一个 BiConsumer。我们演示了命名的和内联的 BiConsumer 变体。
专门的 Consumers
Java 为原始类型提供了专门的 Consumer 接口,以避免装箱开销。这些包括 IntConsumer、DoubleConsumer 和 LongConsumer。示例使用原始消费者。
package com.zetcode;
import java.util.function.IntConsumer;
import java.util.function.DoubleConsumer;
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
int[] integers = {1, 2, 3, 4, 5};
double[] doubles = {1.1, 2.2, 3.3, 4.4, 5.5};
// IntConsumer example
IntConsumer squarePrinter = i ->
System.out.println(i + " squared is " + (i * i));
Arrays.stream(integers).forEach(squarePrinter);
// DoubleConsumer example
DoubleConsumer rounder = d ->
System.out.println(d + " rounded is " + Math.round(d));
Arrays.stream(doubles).forEach(rounder);
}
}
此示例演示了原始类型专用的消费者。IntConsumer 处理 int 值,无需装箱。DoubleConsumer 处理 double 值。这些专业化提高了对原始类型密集型操作的性能。
来源
在本文中,我们介绍了 Java Consumer 接口的基本方法和特性。理解这些概念对于现代 Java 应用程序中的函数式编程和集合处理至关重要。
作者
列出所有Java教程。