与Java 8 Streams并行映射到多个映射

时间:2018-07-13 19:19:46

标签: concurrency java-8 hashmap iterator java-stream

我正在遍历CloseableIterator(在元素上循环),目前正在添加到哈希表中(只是放入HashMap中,根据需要处理冲突)。我的目标是并行执行此过程,并使用并行性将其添加到块中的多个哈希图中以加快该过程。然后简化为单个哈希图。

不确定第一步,使用流并行映射到多个哈希表。感谢帮助。

2 个答案:

答案 0 :(得分:0)

收集到Collectors.toMap中的并行流将已经在多个线程上处理该流,然后将每个线程的映射合并为最后一步。或者在"I'm $HOME"的情况下,多个线程将处理该流并将数据合并到一个线程安全的映射中。

答案 1 :(得分:0)

如果只有Iterator(而不是IterableSpliterator),则可能不值得并行化。乔什·布洛赫(Josh Bloch)在Effective Java中指出:

  

即使在最佳情况下,如果源来自Stream.iterate或使用中间操作limit,并行化管道也不太可能提高其性能。

Iterator仅具有一个next方法,(通常)必须依次调用该方法。因此,任何并行化尝试实际上都是在做Stream.iterate的工作:依次启动流,然后将数据发送到其他线程。传输会带来很多开销,并且缓存根本不在您这边。这很有可能是不值得的,除非可能需要迭代的元素很少并且每个元素上都有很多工作要做。在这种情况下,您最好将它们全部放入ArrayList并从那里并行化。


如果您可以得到一个合理的可并行化的Stream,那就另当别论了。如果您的IterableSpliterator不错,就可以得到这些。如果您的Spliterator不错,则可以使用StreamSupport.stream方法获得Stream。任何Iterable都具有spliterator方法。如果您有Collection,请使用parallelStream方法。

Java中的Map具有键值对,因此我不确定“放入HashMap”是什么意思。对于这个答案,我假设您的意思是您要调用put方法,其中键是元素之一,值是Boolean.TRUE。如果您更新了问题,我可以给出更具体的答案。

在这种情况下,您的代码可能看起来像这样:

public static <E> Map<E, Boolean> putInMap(Stream<E> elements) {
  return elements.parallel()
      .collect(Collectors.toConcurrentMap(e -> e, e -> Boolean.TRUE, (a, b) -> Boolean.TRUE));
}
  • e -> e是键映射器,它使键成为元素。
  • e -> Boolean.TRUE是值映射器,因此设置值是真实的。
  • (a, b) -> Boolean.TRUE是合并功能,决定如何将两个元素合并为一个。