Java: подсчет вхождений элементов списка с groupBy
Быстрый ответ
Для подсчёта количества элементов в списке с использованием Java Streams и метода groupBy
используйте следующий код:
Map<Key, Long> frequencyMap = items.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
В этом сегменте Key
– это тип данных элементов вашего списка, а items
– это ваш список или коллекция. Function.identity()
здесь выступает образом формирования групп, то есть в качестве ключа используется значение элемента.
Подробное рассмотрение GroupBy
Разберём, как функционирует Collectors.groupingBy
. Этот метод осуществляет операции, аналогичные SQL-запросам, но вместо баз данных он работает с коллекциями в Java. Он принимает два аргумента:
- Функцию классификации, определяющую группу для каждого элемента.
- Коллектор, реализующий сокращение количества элементов. Например, с помощью
Collectors.counting()
, можно подсчитать элементы в группе.
Подсчёт пользовательских объектов
Если требуется подсчитать элементы, основываясь на определённых свойствах объектов, используйте структуру вида:
Map<CustomType, Long> counts = customList.stream()
.collect(Collectors.groupingBy(CustomType::getAttribute, Collectors.counting()));
Одновременный подсчёт
Для максимально эффективной работы в многопоточной среде стоит использовать groupingByConcurrent
, обеспечивающий потокобезопасность:
ConcurrentMap<Key, Long> concurrentFrequencyMap = items.parallelStream()
.collect(Collectors.groupingByConcurrent(Function.identity(), Collectors.counting()));
Это гарантирует надёжность и безошибочность обработки данных в многопоточных условиях.
Производительность и альтернативы
Несмотря на удобство использования, Collectors.groupingBy
не всегда является самым быстрым способом обработки данных.
Вариант с использованием ToMap
Для увеличения производительности можно задействовать Collectors.toMap
с функцией объединения Map::merge
:
Map<Key, Long> frequencyMapAlternative = items.stream()
.collect(Collectors.toMap(key -> key, val -> 1L, Math::addExact));
StreamEx для работы с примитивными типами
При работе с примитивными типами для оптимизации производительности можно применить библиотеку StreamEx
:
Map<Key, Integer> frequencyMapStreamEx = StreamEx.of(items)
.groupingBy(Function.identity(), MoreCollectors.countingInt());
Для работы с StreamEx
необходимо добавить соответствующую библиотеку в ваш проект.
Визуализация
Метод groupBy
поможет вам сортировать данные. В качестве примера рассмотрим сгруппированные по эрам коллекционные монеты:
Map<Era, Long> coinCountByEra = coins.stream().collect(
Collectors.groupingBy(Coin::getEra, Collectors.counting())
);
Эра | Количество монет |
---|---|
Бронзовая | 2 |
Серебряная | 4 |
Золотая | 1 |
Проверенный метод вывода на печать
Для вывода результатов на экран используйте entrySet
:
frequencyMap.entrySet().forEach(entry ->
System.out.println(entry.getKey() + ": " + entry.getValue()));
Сложные случаи
Обработка нулевых значений
Чтобы исключить null
-элементы из подсчёта, предварительно воспользуйтесь фильтром:
Map<Object, Long> frequencyMapWithNulls = items.stream()
.filter(Objects::nonNull)
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
Сложные типы
Сложные типы возможно сгруппировать, создав составной ключ или Pair
:
Map<Pair<AttributeType1, AttributeType2>, Long> complexMap = complexList.stream()
.collect(Collectors.groupingBy(
item -> new AbstractMap.SimpleEntry<>(item.getAttribute1(), item.getAttribute2()),
Collectors.counting()
));
Углубленная обработка
Вы также можете выполнять дополнительную обработку полученных данных: сортировать, фильтровать или преобразовывать их для последующего анализа.
Полезные материалы
- Collectors (Java Platform SE 8 ) — Официальная документация метода
Collectors.groupingBy
. - Java Stream collect() Method Examples | DigitalOcean — Статья о методе collect() в контексте
groupingBy
. - DZone Java 8 – Collectors.groupingBy Examples — Примеры использования
groupingBy
в Java 8. - Mkyong.com: Java 8 – How to count duplicates in a List — Инструкция по подсчету дубликатов в списке с использованием Java 8.
- Stack Overflow: How to count the number of occurrences of an element in a List — Советы и обмен опытом на Stack Overflow.