看不到功能接口 'Consumer' 和 'Supplier' 的意义

Failing to see the point of the Functional interfaces 'Consumer' and 'Supplier'

我实现了PredicateFunction的用法,分别用于将松散耦合的条件和函数传递给方法。

谓词经常用于过滤 java 流,例如

list.stream().filter(aPredicate).collect();

和功能:

list.stream().forEach(aFunction);

我没有看到 'Consumer' 和 'Supplier' 的类似用例。一个简单的例子 here 有这样的代码:

Consumer consumer = ConsumerTest::printNames;

consumer.accept("Jeremy");
consumer.accept("Paul");
consumer.accept("Richard");

其中 printNames 是一个简单的方法:

private static void printNames(String name) {
    System.out.println(name);
}

我不明白我为什么不这样做:

Consumer consumer = ConsumerTest::printNames;

printNames("Jeremy");
printNames("Paul");
printNames("Richard");

对我来说似乎是不必要的添加代码,也许那个例子没有显示出它的威力。

您的 list.stream().forEach(aFunction); 示例实际上是错误的,forEach 需要 Consumer<? super T> 而不是 Function<T,R>

这些功能接口的重点在于功能的形状,换句话说,就是这些接口的输入和输出。

要使用您提供的接口:

Predicate<T> 输入:T 类型的值,输出:布尔值,filter 经常使用。

Function<T,R> 输入:T 类型的值,输出:R 类型的值。有点像转换,map 经常使用。

Consumer<T>输入:T类型的值,输出:void/nothing。 forEach 经常使用,在您只想打印一些东西的情况下,或者将值保存到 database/file 而您并不真正关心 return 值的情况。

Supplier<T> input: nothing, output: value of type T. 这可能是最不常见的,因为人们在使用 lambda 时通常从 Collection 开始。但是当你想生成你自己的流时,Supplier 很有用,例如,如果你想生成一个无限的质数流,那么从一个 List 开始是没有办法做到这一点的。

供应商的另一个具体示例是当一个功能需要新对象时,当场创建,例如 Collectors.toCollection(Supplier<C> factory)。例如:

List<T> list = stream.collect(Collectors.toCollection(CopyOnWriteArrayList::new));

在这里,我们传递一个“供应商”……一个不带参数的函数,返回一个值……给 toCollection 方法。

没有 Supplier 类型,我们无法表达。