【问题标题】:Mapping into multiple maps in parallel with Java 8 Streams与 Java 8 Streams 并行映射到多个映射
【发布时间】:2018-12-22 05:10:25
【问题描述】:

我正在对 CloseableIterator 进行迭代(循环遍历元素),目前正在添加到一个 hashmap(只是放入一个 HashMap,根据需要处理冲突)。我的目标是并行执行此过程,使用并行性以块的形式添加多个哈希图以加快该过程。然后缩减为单个 hashmap。

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

【问题讨论】:

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


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

    即使在最好的情况下,如果源来自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 -&gt; e 是键映射器,使键成为元素。
    • e -&gt; Boolean.TRUE 是值映射器,因此设置的值是真实的。
    • (a, b) -&gt; Boolean.TRUE 是合并函数,决定如何将两个元素合并为一个。

    【讨论】:

    • “如果你只有一个迭代器(而不是一个拆分器),那么它可能不值得并行化。”很好奇其中的原因。
    猜你喜欢
    • 2021-10-12
    • 2019-01-19
    • 2018-01-01
    • 1970-01-01
    • 2023-03-21
    • 2021-08-28
    • 1970-01-01
    • 2018-06-18
    • 1970-01-01
    相关资源
    最近更新 更多