我正在查看此code并尝试了解以下代码。
"reviews" => ...
我的问题是每次调用 distinctByKey 并产生新的 ConcurrentHashMap 。如何使用新的ConcurrentHashMap<>(); 维护状态?
答案 0 :(得分:5)
由于这是一个捕获lambda,实际上每次调用都会返回一个新的Predicate
实例 - 但这些实例将共享相同的ConcurrentHashMap
和Function
。
顺便说一下在System.out.println
内添加distinctByKey
- 并看到它实际上只被调用一次。
如果你愿意用:
运行你的例子 Djdk.internal.lambda.dumpProxyClasses=/Your/Path/Here
您会看到为class
的实施生成Predicate
。因为这是一个有状态的lambda - 它捕获CHM
和Function
,它将有一个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
深入了解更多细节