Что такое Stream API в Java?

«Что такое Stream API в Java?» — вопрос из категории Java Core, который задают на 32% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Stream API — это абстракция для декларативной обработки последовательностей данных (коллекций, массивов, I/O каналов) в функциональном стиле, добавленная в Java 8.

Ключевые концепции:

  • Не изменяет источник: Операции над Stream работают с его элементами, но не модифицируют исходную коллекцию.
  • Ленивые вычисления: Промежуточные операции (intermediate) выполняются только при вызове терминальной операции.
  • Конвейер операций: Stream строится как цепочка: источник → промежуточные операции → терминальная операция.
  • Одноразовость: Stream нельзя использовать повторно после вызова терминальной операции.

Типы операций:

  1. Промежуточные (Intermediate): Возвращают новый Stream (ленивые).
    • filter(Predicate<T>) – фильтрация по условию.
    • map(Function<T, R>) – преобразование каждого элемента.
    • sorted() – сортировка.
    • distinct() – удаление дубликатов.
  2. Терминальные (Terminal): Запускают выполнение конвейера и возвращают результат (не Stream).
    • collect(Collector) – агрегация в коллекцию или строку.
    • forEach(Consumer) – выполнение действия для каждого элемента.
    • reduce() – свертка элементов в одно значение.
    • count(), anyMatch(), allMatch() – агрегатные проверки.

Пример:

List<String> names = Arrays.asList("Anna", "Bob", "Alice", "David", "Alex");

List<String> result = names.stream()          // Источник
        .filter(name -> name.length() > 3)    // Промежуточная: оставить имена длиннее 3 букв
        .map(String::toUpperCase)             // Промежуточная: преобразовать в верхний регистр
        .sorted()                             // Промежуточная: отсортировать
        .collect(Collectors.toList());        // Терминальная: собрать в список

System.out.println(result); // Вывод: [ALEX, ALICE, ANNA, DAVID]

Параллельные потоки: Для обработки больших данных можно использовать parallelStream() для автоматического распараллеливания операций по ядрам процессора.