Predicate如何在Java 8中维护状态

时间:2017-11-20 08:06:31

标签: java-8 java-stream

我正在查看此code并尝试了解以下代码。

从Stuart Marks回复

"reviews" => ...

我的问题是每次调用 distinctByKey 并产生新的 ConcurrentHashMap 。如何使用新的ConcurrentHashMap<>(); 维护状态?

3 个答案:

答案 0 :(得分:5)

由于这是一个捕获lambda,实际上每次调用都会返回一个新的Predicate实例 - 但这些实例将共享相同的ConcurrentHashMapFunction

顺便说一下在System.out.println内添加distinctByKey - 并看到它实际上只被调用一次。

如果你愿意用:

运行你的例子

Djdk.internal.lambda.dumpProxyClasses=/Your/Path/Here

您会看到为class的实施生成Predicate。因为这是一个有状态的lambda - 它捕获CHMFunction,它将有一个private构造函数和一个返回实例的static factory method。因此,每当元素通过流管道时,将会创建Predicate不同的实例 - 但所有这些实例将共享相同的ConcurrentHashMap和{{1} }。

答案 1 :(得分:4)

看起来很混乱,但很简单。实际发生的是distinctByKey方法只被称为一次,因此只有ConcurrentHashMap的一个实例,并且它由lambda表达式捕获。因此,当distinctByKey方法返回Predicate对象时,我们会将其应用于流的每个元素。

答案 2 :(得分:4)

  

“我的问题是每次 distinctByKey 都会被调用   产生新的ConcurrentHashMap。它如何维持状态使用   新的ConcurrentHashMap<>(); ?“

以下是每次都不会调用 distinctByKey 的事实。您可以检查是否修改 distinctByKey 并将 sysout 放入其中。

public static <T> Predicate<T> distinctByKey(Function<? super T,Object> keyExtractor) {
    System.out.println("Hello Java 8 !!");
    Map<Object,Boolean> seen = new ConcurrentHashMap<>();
    return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}

distinctByKey 基本上做的是返回一个谓词,并在返回的谓词条件上测试每个元素。并且所有那些谓词共享相同的并发hashmap。使用 Eugene answer

深入了解更多细节

enter image description here