使用方法主体的Java 8谓词仅被调用一次?

时间:2019-05-27 13:01:07

标签: java java-8 predicate

我已经检查了以下代码段:

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"));

我可以看到方法的主体确实在每一行中都被调用。是什么使过滤器的主体仅被调用一次?

3 个答案:

答案 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的引用,它在执行工作时会使用和修改。