Java Consumer接口,用户希望编写实现 java.util.function.Consumer 包的 lambda 表达式,可以使用 lambda 表达式或方法引用来实现 void accept(T t) 方法。例 2-1 列出了 Consumer 接口定义的方法,其单一抽象方法为 void accept(T t)。
Java Consumer接口 问题描述
用户希望编写实现 java.util.function.Consumer 包的 lambda 表达式。
Java Consumer接口 解决方案
使用 lambda 表达式或方法引用来实现 void accept(T t) 方法。
Java Consumer接口 具体实例
例 2-1 列出了 Consumer 接口定义的方法,其单一抽象方法为 void accept(T t)。
例 2-1
Consumer接口定义的方法
void accept(T t) ➊
default Consumer<T> andThen(Consumer<? super T> after) ➋
❶ 单一抽象方法
❷ 用于复合操作的默认方法
accept 方法传入一个泛型参数并返回 void。在所有传入 Consumer 作为参数的方法中,最常见的是 java.util.Iterable 接口的默认 forEach 方法,如例 2-2 所示。
例 2-2
Iterable接口定义的forEach方法
default void forEach(Consumer<? super T> action) ➊
➊ 将可迭代集合(iterable collection)中的所有元素传递给 Consumer 参数
如例 2-3 所示,所有线性集合通过对集合中每个元素执行给定的操作来实现 Iterable 接口。
例 2-3 打印集合中的元素
List<String> strings = Arrays.asList("this", "is", "a", "list", "of", "strings");
strings.forEach(new Consumer<String>() { ➊
@Override
public void accept(String s) {
System.out.println(s);
}
});
strings.forEach(s -> System.out.println(s)); ➋
strings.forEach(System.out::println); ➌
❶ 匿名内部类实现
❷ lambda 表达式
❸ 方法引用
在本例中,由于 accept 方法只传入一个参数且不返回任何值,其签名与 lambda 表达式相符。通过 System.out 访问 PrintStream 类的 println 方法,它与 Consumer 相互兼容。因此,最后两条语句都可以作为 Consumer 参数的目标。
如表 2-1 所示,java.util.function 包还定义了三种 Consumer<T> 的基本变体,以及一种双参数形式。
表2-1:其他Consumer接口
| 接口 | 单一抽象方法 |
|---|---|
IntConsumer |
void accept(int x) |
DoubleConsumer |
void accept(double x) |
LongConsumer |
void accept(long x) |
BiConsumer |
void accept(T t, U u) |
Consumer接口期望执行带有副作用的操作(即它可能会改变输入参数的内部状态),参见范例 Predicate接口
BiConsumer 接口的 accept 方法传入两个泛型参数,这两个泛型参数应为不同的类型。java.util.function 包定义了 BiConsumer 接口的三种变体,每种变体的第二个参数为基本数据类型。以 ObjIntConsumer 接口为例,其 accept 方法传入两个参数,分别为泛型参数和 int 参数。ObjLongConsumer 和 ObjDoubleConsumer 接口的定义与 ObjIntConsumer 类似。
标准库还支持 Consumer 接口的一些其他用法。
Optional.ifPresent(Consumer<? super T> consumer)
如果值存在,则调用指定的 consumer;否则不进行任何操作。
Stream.forEach(Consumer<? super T> action)
对流的每个元素执行操作 1。Stream.forEachOrdered 方法与之类似,它根据元素的出现顺序(encounter order)访问元素。
1这项操作十分常见,因此 Iterable 接口也直接定义了 forEach 方法。当源元素不是来自集合或需要创建并行流时,Stream.forEach 方法就很有用。
Stream.peek(Consumer<? super T> action)
首先执行给定操作,再返回一个与现有流包含相同元素的流。peek 方法在调试中极为有用(参见范例 利用peek方法对流进行调试)。
极客教程