Collectors
Collector описывает, как собрать результат
Stream.toList() отлично подходит, когда нужен обычный список.
Но иногда элементы нужно объединить в строку, сгруппировать по признаку
или превратить в Map. Для таких задач используется терминальная операция
collect() вместе с готовыми collector-ами из класса Collectors.
joining объединяет строки
String result = Stream.of("Java", "Spring", "SQL")
.collect(Collectors.joining(", "));
В result будет строка Java, Spring, SQL.
У joining также есть варианты с префиксом и суффиксом,
если нужно сразу получить оформленную строку.
groupingBy собирает элементы по ключу
groupingBy вычисляет ключ для каждого элемента
и помещает элементы с одинаковым ключом в одну группу.
Map<Integer, List<String>> byLength =
Stream.of("Java", "SQL", "Spring", "HTTP")
.collect(Collectors.groupingBy(String::length));
Ключом здесь становится длина строки. В результате строки длины 4
окажутся в одной группе, длины 3 — в другой и так далее.
Похожая операция partitioningBy делит элементы ровно на две группы
по результату Predicate.
toMap строит отображение
Map<String, Integer> lengths =
Stream.of("Java", "Spring", "SQL")
.collect(Collectors.toMap(
word -> word,
String::length
));
Первое правило создаёт ключ, второе — значение.
Если два элемента дадут одинаковый ключ, простой вариант toMap
не сможет выбрать победителя и выбросит исключение.
Для таких данных нужно заранее определить функцию объединения значений.
Map<Integer, String> oneWordByLength =
Stream.of("Java", "HTTP", "Spring")
.collect(Collectors.toMap(
String::length,
word -> word,
(left, right) -> left
));
Stream.toList() и Collectors.toList() — не полные аналоги.
Stream.toList() возвращает неизменяемый список.
У Collectors.toList() нет гарантии конкретной реализации и изменяемости результата.
Если нужна определённая коллекция, лучше выразить это явно.