Java for Beginner
674 subscribers
554 photos
156 videos
12 files
845 links
Канал от новичков для новичков!
Изучайте Java вместе с нами!
Здесь мы обмениваемся опытом и постоянно изучаем что-то новое!

Наш YouTube канал - https://www.youtube.com/@Java_Beginner-Dev

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
Collectors в Java

groupingBy

Collectors.groupingBy – один из самых мощных коллекторов в Java Stream API, позволяющий группировать элементы потока по заданному критерию. Возвращает Map<K, List<T>>, где ключ (K) – это значение классификатора, а значение – список элементов, соответствующих этому ключу.

1. Базовая форма:
groupingBy(classifier)
Группирует элементы по ключу, возвращаемому classifier (функцией классификации).

Сигнатура:
public static <T, K> Collector<T, ?, Map<K, List<T>>> groupingBy(  
Function<? super T, ? extends K> classifier
)


Пример:
List<String> names = List.of("Alice", "Bob", "Charlie", "Anna", "Alex");  

Map<Integer, List<String>> groupedByLength = names.stream()
.collect(Collectors.groupingBy(String::length));

// Результат:
// {3=[Bob], 4=[Anna, Alex], 5=[Alice], 7=[Charlie]}


Как это работает внутри?

Классификатор (String::length) вычисляет ключ для каждого элемента.
Элементы с одинаковым ключом добавляются в List<T>.
По умолчанию используется HashMap, а значения хранятся в ArrayList.


2. groupingBy(classifier, downstream) – с дополнительным коллектором
Позволяет указать, как собирать элементы в группы (не только в List).

Сигнатура:
public static <T, K, A, D> Collector<T, ?, Map<K, D>> groupingBy(  
Function<? super T, ? extends K> classifier,
Collector<? super T, A, D> downstream
)


Примеры:

2.1. Группировка в Set вместо List
Map<Integer, Set<String>> groupedByLength = names.stream()  
.collect(Collectors.groupingBy(
String::length,
Collectors.toSet()
));


2.2. Подсчет количества элементов в каждой группе
Map<Integer, Long> countByLength = names.stream()  
.collect(Collectors.groupingBy(
String::length,
Collectors.counting()
));
// Результат: {3=1, 4=2, 5=1, 7=1}


2.3. Объединение элементов в строку
Map<Integer, String> joinedNames = names.stream()  
.collect(Collectors.groupingBy(
String::length,
Collectors.joining(", ")
));

// Результат: {3="Bob", 4="Anna, Alex", 5="Alice", 7="Charlie"}


3. groupingBy(classifier, mapFactory, downstream) – с выбором реализации Map
Позволяет указать конкретную реализацию Map (например, TreeMap или LinkedHashMap).

Сигнатура:
public static <T, K, D, A, M extends Map<K, D>> Collector<T, ?, M> groupingBy(  
Function<? super T, ? extends K> classifier,
Supplier<M> mapFactory,
Collector<? super T, A, D> downstream
)


Пример:

// Группировка с сохранением порядка (LinkedHashMap)  
LinkedHashMap<Integer, List<String>> orderedGroups = names.stream()
.collect(Collectors.groupingBy(
String::length,
LinkedHashMap::new,
Collectors.toList()
));

// Группировка с сортировкой по ключу (TreeMap)
TreeMap<Integer, Set<String>> sortedGroups = names.stream()
.collect(Collectors.groupingBy(
String::length,
TreeMap::new,
Collectors.toSet()
));


4. Многокритериальная группировка (вложенные groupingBy)
Можно группировать по нескольким уровням, создавая сложные структуры данных.

Пример:
record Person(String name, String city, int age) {}  

List<Person> people = List.of(
new Person("Alice", "NY", 25),
new Person("Bob", "LA", 30),
new Person("Charlie", "NY", 25),
new Person("David", "LA", 35)
);

// Группировка по городу, а затем по возрасту
Map<String, Map<Integer, List<Person>>> multiLevelGroup = people.stream()
.collect(Collectors.groupingBy(
Person::city,
Collectors.groupingBy(Person::age)
));

// Результат:
// {
// "NY": {25=[Alice, Charlie]},
// "LA": {30=[Bob], 35=[David]}
// }


5. Производительность и особенности

Порядок элементов в группах зависит от исходного потока (если он ordered, как в List, порядок сохраняется).
Хэш-коллизии обрабатываются через HashMap.


Нюансы при параллельных стримах:
Если используется ConcurrentHashMap, группировка становится потокобезопасной.
В некоторых случаях groupingByConcurrent работает быстрее.


#Java #Training #Medium #Collectors #groupingBy