Когда использовать Collectors.groupingByConcurrent? - PullRequest
0 голосов
/ 02 марта 2019

Я не понимаю точного варианта использования Collectors.groupingByConcurrent.Из JavaDocs:

Возвращает параллельный Collector, реализующий каскадную операцию «group by» для элементов ввода типа T ...Это параллельный и неупорядоченный коллектор....

Возможно, здесь ключевыми словами являются каскадный "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 (конечно, это не может быть просто для получения группировок в качестве параллельной карты)?

1 Ответ

0 голосов
/ 02 марта 2019

Все коллекторы прекрасно работают для параллельных потоков, но коллекторы, поддерживающие прямой параллелизм (с Collector.Characteristics.CONCURRENT), имеют право на оптимизации, которых нет у других.groupingByConcurrent попадает в эту категорию.

(Грубо говоря, непоследовательный коллектор разбивает входные данные на части для каждого потока, создает аккумулятор для каждого потока и затем объединяет их в конце. AПараллельный (и неупорядоченный) коллектор создает один аккумулятор и имеет несколько рабочих потоков, одновременно объединяющих элементы в один и тот же аккумулятор.)

...