我意识到Predicate
和Function
的用法,分别用于将松散耦合的条件和函数传递给方法。
谓词经常用于过滤java流,例如
list.stream().filter(aPredicate).collect();
和功能:
list.stream().forEach(aFunction);
我没有看到“消费者”和“供应商”的类似用例。一个简单的例子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");
看起来像是不必要的添加代码,也许这个例子没有显示它的力量。
答案 0 :(得分:2)
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
大量使用,在您只想打印出来的情况下,或者将值保存到您并不真正关心返回值的数据库/文件中。
Supplier<T>
输入:没有,输出:类型为T的值。这可能是最不常见的,因为人们在使用lambda时经常以Collection开头。但是,当您想要生成自己的流时,供应商很有用,例如,如果要生成无限的素数流,则无法通过以列表开头来实现。
答案 1 :(得分:2)
供应商的另一个具体示例是,当场创建的函数需要新的Object,例如Collectors.toCollection(Supplier<C> factory)
。例如:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
int a;
ifstream inputfile;
//declare an input file
inputfile.open("text.txt");
while(//not sure best way to do this part)
{
//guessing I can use a for loop and place numbers in array
//based on first number in the row of numbers
}
return 0;
}
在这里,我们传递一个“供应商”......一个不带参数的函数,将一个值...返回给List<T> list = stream.collect(Collectors.toCollection(CopyOnWriteArrayList::new));
方法。
如果没有toCollection
类型,我们就无法表达。