1. Обзор
В этом коротком руководстве мы увидим, как мы можем группировать одинаковые объекты и подсчитывать их количество в Java. Мы будем использовать сборщик groupingBy()
в Java.
2. Подсчет вхождений с помощью Collectors.groupingBy()
Collectors.groupingBy()
предоставляет функциональные возможности, аналогичные предложению GROUP BY в SQL. Мы можем использовать это для группировки объектов по любому атрибуту и сохранения результатов в Map
.
Например, давайте рассмотрим сценарий, в котором нам нужно сгруппировать одинаковые String
в потоке и подсчитать их вхождения:
List<String> list = new ArrayList<>(Arrays.asList("Foo", "Bar", "Bar", "Bar", "Foo"));
Мы можем сгруппировать одинаковые строки, которые в данном случае будут «Foo» и «Bar». Результирующая Карта
будет хранить эти строки как ключи. Значения для этих ключей будут количеством вхождений. Значение для «Foo» будет равно 2, а для «Bar» будет равно 3:
Map<String, Long> result = list.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
Assert.assertEquals(new Long(2), result.get("Foo"));
Assert.assertEquals(new Long(3), result.get("Bar"));
Давайте расшифруем приведенный выше фрагмент кода:
Результат Map<String, Long>
— это выходной результатMap
, который будет хранить сгруппированные элементы как ключи и подсчитывать их вхождения как значения.list.stream() — мы
конвертируем элементы списка в поток Java для обработки коллекции декларативным способом.Collectors.groupingBy()
— это метод классаCollectors
для группировки объектов по некоторому свойству и сохранения результатов в экземпляреMap .
Function.identity() —
это функциональный интерфейс в Java; методidentity
возвращаетфункцию
, которая всегда возвращает свои входные аргументыCollectors.counting()
— этот метод классаCollectors
подсчитывает количество элементов, переданных в потоке в качестве параметра.
Мы могли бы использовать Collectors.groupingByConcurrent()
вместо Collectors.groupingBy().
Он также выполняет операцию группировки над элементами входного потока. Метод собирает результаты в ConcurrentMap
, что повышает эффективность.
Например, для списка ввода:
List<String> list = new ArrayList<>(Arrays.asList("Adam", "Bill", "Jack", "Joe", "Ian"));
Мы можем сгруппировать строки одинаковой длины, используя Collectors.groupingByConcurrent()
:
Map<Integer, Long> result = list.stream()
.collect(Collectors.groupingByConcurrent(String::length, Collectors.counting()));
Assert.assertEquals(new Long(2), result.get(3));
Assert.assertEquals(new Long(3), result.get(4));
3. Заключение
В этой статье мы рассмотрели использование Collector.groupingBy()
для группировки одинаковых объектов.
И в завершение вы найдете исходный код этой статьи на GitHub .