代码之家  ›  专栏  ›  技术社区  ›  ernest_k Petronella

何时使用Collectors.groupingByConcurrent?

  •  1
  • ernest_k Petronella  · 技术社区  · 6 年前

    我无法理解 Collectors.groupingByConcurrent . 来自JavaDocs:



    ...

    级联“分组方式” . 这是否意味着收藏者是如何进行实际积累的(从源头上看,它很快变得错综复杂)


    当我用一个 ConcurrentMap

    class FakeConcurrentMap<K, V> extends HashMap<K, V> 
        implements ConcurrentMap<K, V> {}
    

    我看到它用并行流中断(由于映射不是线程安全的,所以给出了错误的聚合):

    Map<Integer, Long> counts4 = IntStream.range(0, 1000000)
            .boxed()
            .parallel()
            .collect(
                Collectors.groupingByConcurrent(i -> i % 10, 
                                              FakeConcurrentMap::new, 
                                              Collectors.counting()));
    

    .parallel() ,结果一致正确。看来 groupingByConcurrent 与平行流一起。

    但是,据我所知,下面的并行流 groupingBy 始终产生正确的结果:

    Map<Integer, Long> counts3 = IntStream.range(0, 1000000)
            .boxed()
            .parallel()
            .collect(
                Collectors.groupingBy(i -> i % 10, 
                                      HashMap::new,
                                      Collectors.counting()));
    

    那么什么时候使用才是正确的呢 而不是 分组依据 (当然,这不可能仅仅是将分组作为一个并发映射)?

    0 回复  |  直到 6 年前
        1
  •  8
  •   Louis Wasserman    6 年前

    所有收集器对于并行流都可以正常工作,但是收集器支持直接并发(使用 Collector.Characteristics.CONCURRENT groupingByConcurrent 属于这一类。

    (大致来说,发生的情况是非并发收集器将输入分解为每个线程的片段,为每个线程创建一个累加器,然后在最后合并它们。并发(无序)收集器创建一个累加器,并有多个工作线程并发地将元素合并到同一个累加器中。)