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

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

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Забыл напомнить Вам что мы вновь встречаемся в 16:00 по МСК в Яндекс телемост!))))

А то опять никто не придет😂😂😂


Приходите давайте)))😎
Please open Telegram to view this post
VIEW IN TELEGRAM
Ребят, спешу извиниться, но видео я сегодня не выложу, так как неизвестный ублюдок заспамил конец встречи 😡

Обработаю и завтра выложу.

Надеюсь на понимание 🤙
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Collectors в Java

Collectors.toMap

Collectors.toMap – это мощный коллектор, преобразующий элементы потока в Map<K, V>, где ключи и значения вычисляются на основе элементов потока.

1. Базовая форма: toMap(keyMapper, valueMapper)

Преобразует поток в Map, где:
keyMapper – функция, вычисляющая ключ,
valueMapper – функция, вычисляющая значение.


Сигнатура:
public static <T, K, U> Collector<T, ?, Map<K, U>> toMap(  
Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper
)


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

// Создаем Map: {имя -> длина строки}
Map<String, Integer> nameToLength = names.stream()
.collect(Collectors.toMap(
name -> name, // ключ – сама строка
name -> name.length() // значение – длина строки
));

// Результат: {"Alice":5, "Bob":3, "Charlie":7}
Что произойдет, если ключи повторяются?
→ Будет выброшено IllegalStateException!


2. Обработка дубликатов: toMap(keyMapper, valueMapper, mergeFunction)

Если возможны повторяющиеся ключи, нужно указать mergeFunction – стратегию разрешения конфликтов.

Сигнатура:
public static <T, K, U> Collector<T, ?, Map<K, U>> toMap(  
Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper,
BinaryOperator<U> mergeFunction
)


Примеры:

2.1. Оставить старое значение
List<String> names = List.of("Alice", "Bob", "Alice");  

Map<String, Integer> nameToLength = names.stream()
.collect(Collectors.toMap(
name -> name,
name -> name.length(),
(oldValue, newValue) -> oldValue // при конфликте берем старое значение
));

// Результат: {"Alice":5, "Bob":3}


2.2. Объединить значения (например, конкатенация строк)
List<String> names = List.of("A", "B", "A", "C");  

Map<String, String> mergedLetters = names.stream()
.collect(Collectors.toMap(
letter -> letter,
letter -> letter,
(oldVal, newVal) -> oldVal + newVal // "A" + "A" → "AA"
));

// Результат: {"A":"AA", "B":"B", "C":"C"}


2.3. Суммирование значений при дублировании ключей
record Product(String id, double price) {}  

List<Product> products = List.of(
new Product("A", 10.0),
new Product("B", 20.0),
new Product("A", 15.0)
);

Map<String, Double> totalPriceById = products.stream()
.collect(Collectors.toMap(
Product::id,
Product::price,
Double::sum // 10.0 + 15.0 = 25.0
));

// Результат: {"A":25.0, "B":20.0}


3. Выбор реализации Map: toMap(keyMapper, valueMapper, mergeFunction, mapFactory)

Позволяет указать конкретную реализацию Map (например, LinkedHashMap или TreeMap).

Сигнатура:
public static <T, K, U, M extends Map<K, U>> Collector<T, ?, M> toMap(  
Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper,
BinaryOperator<U> mergeFunction,
Supplier<M> mapFactory
)


Примеры:

3.1. Сохранение порядка вставки (LinkedHashMap)
Map<String, Integer> orderedMap = names.stream()  
.collect(Collectors.toMap(
name -> name,
name -> name.length(),
(oldVal, newVal) -> oldVal,
LinkedHashMap::new
));


3.2. Сортировка по ключу (TreeMap)
Map<String, Integer> sortedMap = names.stream()  
.collect(Collectors.toMap(
name -> name,
name -> name.length(),
(oldVal, newVal) -> oldVal,
TreeMap::new
));


#Java #Training #Medium #Collectors #CollectorsToMap
4. Особенности и подводные камни

4.1. Null-ключи и Null-значения
HashMap допускает один null-ключ, но если keyMapper возвращает null – будет NullPointerException.
Если valueMapper возвращает null, значение в Map будет null.


4.2. Параллельные стримы
toMap не оптимизирован для параллельных операций.
Вместо него лучше использовать Collectors.toConcurrentMap.


4.3. Изменяемые ключи
Если ключ изменяется после добавления в Map, это может нарушить работу HashMap (ключи должны быть immutable).

5. Альтернативы


5.1. Collectors.toUnmodifiableMap (Java 10+)
Создает неизменяемую Map:

Map<String, Integer> unmodifiableMap = names.stream()  
.collect(Collectors.toUnmodifiableMap(
name -> name,
name -> name.length()
));


5.2. Collectors.toConcurrentMap
Оптимизирован для многопоточности:

ConcurrentMap<String, Integer> concurrentMap = names.stream()  
.collect(Collectors.toConcurrentMap(
name -> name,
name -> name.length()
));


#Java #Training #Medium #Collectors #CollectorsToMap
Что выведет код?

import java.util.*;

public class Task280425 {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3));
List<Integer> subList = list.subList(1, 3);
subList.add(4);

System.out.println(list.size());
}
}


#Tasks
Варианты ответа:
Anonymous Quiz
7%
2
43%
3
32%
4
18%
Exception какой-то
И ведь всегда так 😡 😁

https://t.me/Java_for_beginner_dev

#Mems
Please open Telegram to view this post
VIEW IN 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
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM