我无法理解Collectors.groupingByConcurrent的确切用例。
从JavaDocs:



也许这里的关键字是级联的“group by”。这是否表明收集器如何进行实际积累? (从源头上看,它变得非常复杂)

当我用假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()));

因此,什么时候使用groupingByConcurrent而不是groupingBy(确定不能仅仅将分组作为并发映射)是正确的?

最佳答案

所有收集器对于并行流都可以正常工作,但是支持直接并发(使用Collector.Characteristics.CONCURRENT)的收集器可以进行其他优化所不具备的优化。 groupingByConcurrent属于这一类。

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

关于java - 何时使用Collectors.groupingByConcurrent?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54962156/

10-10 04:11