Stream collect и Collectors
collect — главная терминальная операция Stream API, когда нужно собрать
результат в коллекцию или агрегат. Она принимает Collector — стратегию
сборки. В классе java.util.stream.Collectors уже есть готовые сборщики
на все типовые случаи: список, множество, словарь, строку, группировку,
подсчёт и так далее.
Часто используемые Collectors
Collectors.toList()
Collectors.toSet()
Collectors.toMap(keyFn, valueFn)
Collectors.joining(", ", "[", "]")
Collectors.counting()
Collectors.summingInt(fn) / averagingInt(fn)
Collectors.groupingBy(classifier)
Collectors.partitioningBy(predicate)
Примеры
Пример 1. toList и toSet
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public class CollectBasic {
public static void main(String[] args) {
List<Integer> raw = Arrays.asList(1, 2, 2, 3, 3, 3);
List<Integer> list = raw.stream().collect(Collectors.toList());
Set<Integer> set = raw.stream().collect(Collectors.toSet());
System.out.println(list);
System.out.println(set);
}
}
Output:
[1, 2, 2, 3, 3, 3]
[1, 2, 3]
Пример 2. joining
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class JoiningDemo {
public static void main(String[] args) {
List<String> sensors = Arrays.asList("ИК", "УЗ", "Линия");
String csv = sensors.stream().collect(Collectors.joining(", "));
String pretty = sensors.stream().collect(Collectors.joining(", ", "[", "]"));
System.out.println(csv);
System.out.println(pretty);
}
}
Output:
ИК, УЗ, Линия
[ИК, УЗ, Линия]
Пример 3. toMap
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class ToMapDemo {
public static void main(String[] args) {
List<String> sensors = Arrays.asList("ик", "уз", "линия");
Map<String, Integer> lens = sensors.stream()
.collect(Collectors.toMap(s -> s, String::length));
System.out.println(lens);
}
}
Output:
{ик=2, уз=2, линия=5}
Пример 4. groupingBy
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class GroupingDemo {
public static void main(String[] args) {
List<String> words = Arrays.asList("ик", "уз", "линия", "led", "серво", "вкл");
Map<Integer, List<String>> byLen = words.stream()
.collect(Collectors.groupingBy(String::length));
System.out.println(byLen);
}
}
Output:
{2=[ик, уз], 3=[led, вкл], 5=[линия, серво]}
Пример 5. groupingBy + counting
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class GroupingCount {
public static void main(String[] args) {
List<String> events = Arrays.asList("старт", "стоп", "старт", "пауза", "стоп", "старт");
Map<String, Long> counts = events.stream()
.collect(Collectors.groupingBy(e -> e, Collectors.counting()));
System.out.println(counts);
}
}
Output:
{пауза=1, стоп=2, старт=3}
Пример 6. partitioningBy
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class PartitionDemo {
public static void main(String[] args) {
List<Integer> distances = Arrays.asList(5, 12, 30, 8, 100, 3);
Map<Boolean, List<Integer>> parts = distances.stream()
.collect(Collectors.partitioningBy(d -> d >= 10));
System.out.println("Близко: " + parts.get(false));
System.out.println("Далеко: " + parts.get(true));
}
}
Output:
Близко: [5, 8, 3]
Далеко: [12, 30, 100]
Подводные камни
Предупреждение
Collectors.toMapброситIllegalStateException, если встретит дубликат ключа. Используйте перегрузку с merge-функцией:toMap(k, v, (a, b) -> a).Порядок ключей в
Collectors.toMapне гарантируется. Нужен порядок — используйтеtoMap(..., LinkedHashMap::new).В Java 16+ есть
Stream.toList()— возвращает неизменяемый список, в отличие отCollectors.toList().groupingByсоздаёт пустой список для отсутствующих групп только если вы сами их добавите — он группирует только то, что реально пришло.joiningпринимаетCharSequence: элементы потока должны быть строками (или предварительно превращены черезmap).
См. также
Примечание
Материал подготовлен по мотивам документации пакета java.util.stream
и класса java.util.stream.Collectors, распространяется в рамках
Oracle Free Documentation License. Текст написан своими словами,
примеры кода — оригинальные.