有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java何时使用收集器。按并发分组?

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

Returns a concurrent Collector implementing a cascaded "group by" operation on input elements of type T...
This is a concurrent and unordered Collector.
...

也许这里的关键词是级联的“分组方式”。这是否表明了催收员是如何进行实际积累的?(从源头上看,它很快变得错综复杂)


当我用一个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是正确的(当然,这不能仅仅是将分组作为并发映射获得)


共 (1) 个答案

  1. # 1 楼答案

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

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