← Назад к вопросам

Что делает collect?

1.6 Junior🔥 191 комментариев
#Soft Skills и карьера

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое collect в Stream API

collect() — это терминальная операция в Stream API, которая преобразует поток элементов в контейнер (коллекцию). Это один из самых мощных инструментов обработки данных в Java 8+.

Основное назначение

Метод collect() собирает элементы потока в контейнер (List, Set, Map и т.д.) с помощью Collector'а. Он выполняет:

  1. Поставку (supplier) — создание пустого контейнера
  2. Накопление (accumulator) — добавление элементов в контейнер
  3. Объединение (combiner) — слияние промежуточных результатов (для параллельных потоков)

Простые примеры

// Собрать в List
List<String> names = stream.collect(Collectors.toList());

// Собрать в Set
Set<String> uniqueNames = stream.collect(Collectors.toSet());

// Собрать в Map
Map<Integer, String> idToName = stream.collect(
    Collectors.toMap(Person::getId, Person::getName)
);

Продвинутые примеры

// Группировка по параметру
Map<String, List<Person>> byDepartment = people.stream()
    .collect(Collectors.groupingBy(Person::getDepartment));

// Группировка с подсчётом
Map<String, Long> countByDept = people.stream()
    .collect(Collectors.groupingBy(
        Person::getDepartment,
        Collectors.counting()
    ));

// Соединение строк
String names = people.stream()
    .map(Person::getName)
    .collect(Collectors.joining(", "));

// Разделение по условию
Map<Boolean, List<Person>> adults = people.stream()
    .collect(Collectors.partitioningBy(
        person -> person.getAge() >= 18
    ));

Анатомия Collector

Collector<T, A, R> имеет 4 компонента:

1. supplier() — создаёт аккумулятор (например, new ArrayList<>())
2. accumulator() — функция (a, t) -> { a.add(t); }
3. combiner() — объединяет два аккумулятора (для параллельных потоков)
4. finisher() — финальное преобразование результата

Кастомный Collector

// Собрать в String через запятую без Collectors.joining()
Collector<String, StringBuilder, String> customJoiner = Collector.of(
    StringBuilder::new,           // supplier
    (sb, s) -> sb.append(s).append(", "),  // accumulator
    (sb1, sb2) -> sb1.append(sb2),         // combiner
    sb -> sb.substring(0, Math.max(0, sb.length() - 2))  // finisher
);

String result = names.stream().collect(customJoiner);

Важные различия

ОперацияВозвращаетИспользование
toList()ListГибкая коллекция
toSet()SetУникальные элементы
toUnmodifiableList()ListНеизменяемая коллекция
toMap()MapКлюч-значение пары
joining()StringОбъединение строк
groupingBy()MapГруппировка по критерию
partitioningBy()Map<Boolean, List>Разделение на две группы

Параллельная обработка

// Параллельный поток
List<Integer> result = list.parallelStream()
    .filter(n -> n % 2 == 0)
    .collect(Collectors.toList());

// При параллельной обработке combiner() вступает в силу

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

collect() оптимален для:

  • Преобразования потока в коллекцию
  • Группировки и партиционирования
  • Объединения результатов

Использование кастомного Collector'а может быть дороже, чем простые циклы, если не требуется функциональный стиль.

Вывод: collect() — это универсальный инструмент для преобразования потоков данных в контейнеры различных типов, от простых List'ов до сложных структур данных с группировкой и фильтрацией.