Java 8 个使用方法体的谓词只被调用一次?

Java 8 predicates using methods bodies are called only once?

我检查了以下片段:

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

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

distinctByKey returns 缓存 ConcurrentHashMapPredicate 单个 实例。例如,如果您通过 lambda 将 Predicate 的创建替换为匿名内部 class,则您可以获得几乎相同的结果。

当您调用 .filter(distinctByKey(Function.identity())) 时,将评估传递给 filter() 的参数。那是唯一一次 distinctByKey(Function.identity()) 被执行并且 returns 是 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"));

I thought that the distinctByKey method is called or interpreted in each iteration of the Stream i mean the Map being instance in each turn but it's not! my question is the body of the Predicate method call only one time? in the Stream iteration is this a assertion?

没有。流不是魔法,它们不会推翻标准 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.

的影响

在您的情况下发生的情况是,您的 distinctByKey() 方法(唯一调用)返回的 Predicate 不止一次被 使用 作为处理嵌入它的流。 Predicate 包含对 Map 的引用,它在执行其工作时使用和修改它。