我已经检查了以下代码段:
public static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
Map<Object, Boolean> computed = new ConcurrentHashMap<>();/*IS THIS LINE CALLED ONCE ON STREAM->FILTER NOT MATTER HOW LONG THE STREAM IS*/
return t -> {return computed.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;};
}
private void test(){
final long d = Stream.of("JOHN","STEPHEN","ORTIZ","RONDON")
.filter(distinctByKey(Function.identity()))
.count();
System.out.println("d = " + d);
}
此代码不是我的。我知道在这个示例中使用ConcurrentMap
不是正确的选择,在这种情况下,我应该使用ConcurrentMap
而不是Map
,但这不是我关心的问题。
我认为distinctByKey
的每次迭代都调用或解释Stream
方法。我的意思是Map
每次都实例化,但事实并非如此!
Predicate
方法的主体是否仅被调用过一次?
在Stream
迭代中,这是一个断言吗?
因为当我尝试以下代码时:
final Function<String,Integer>a = (name)->name.length();
System.out.println(distinctByKey(a).test("JOHN"));
System.out.println(distinctByKey(a).test("STEPHEN"));
System.out.println(distinctByKey(a).test("ORTIZ"));
System.out.println(distinctByKey(a).test("RONDON"));
我可以看到方法的主体确实在每一行中都被调用。是什么使过滤器的主体仅被调用一次?
答案 0 :(得分:4)
distinctByKey
返回Predicate
的单个实例,该实例缓存ConcurrentHashMap
。例如,如果您通过lambda将Predicate
的创建替换为匿名内部类,则可以实现几乎相同的目的。
答案 1 :(得分:4)
调用.filter(distinctByKey(Function.identity()))
时,将评估传递给filter()
的参数。这是唯一执行distinctByKey(Function.identity())
并返回Predicate<String>
实例的时间。
然后多次评估Predicate
(即执行test()
方法),每次评估Stream
的不同元素。
要使您的最后一个片段的行为类似于Stream
管道,它应如下所示:
final Function<String,Integer> a = (name)->name.length();
Predicate<String> pred = distinctByKey(a);
System.out.println(pred.test("JOHN"));
System.out.println(pred.test("STEPHEN"));
System.out.println(pred.test("ORTIZ"));
System.out.println(pred.test("RONDON"));
答案 2 :(得分:4)
我认为在其中调用或解释了distinctByKey方法 Stream的每次迭代,我的意思是Map在每个实例中 转,但不是!我的问题是谓词方法的主体 只打一次电话?在Stream迭代中,这是一个断言吗?
不。流不是魔术,它们也不会推翻标准的Java语义。考虑提供的代码:
final long d = Stream.of("JOHN","STEPHEN","ORTIZ","RONDON") .filter(distinctByKey(Function.identity())) .count();
从图片中选取具有以下一般形式的特定类型和方法:
long x = A.b(y).c(z).d(w);
没有理由期望a()
,b()
或c()
中的任何一个在该链中被多次调用,或者它们的参数被多次评估。不受Stream
的某些类型的影响。
在您的情况下发生的情况是,您的Predicate
方法返回的distinctByKey()
作为唯一的流被多次使用(唯一调用){em>被嵌入处理。 Predicate
包含对Map
的引用,它在执行工作时会使用和修改。