Когда в Java Stream API начинается обработка элементов коллекции?

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

Ответ

Обработка элементов в Stream начинается только при вызове терминальной операции (terminal operation). Все промежуточные операции (intermediate operations) формируют конвейер, но выполняются "лениво" (lazy evaluation).

Почему это важно: Ленивая обработка позволяет оптимизировать работу, например, пропускать ненужные вычисления при коротком замыкании (short-circuiting) в операциях findFirst() или limit().

Пример:

List<Integer> numbers = List.of(1, 2, 3, 4, 5);

// Создание конвейера (ещё не выполняется)
Stream<Integer> stream = numbers.stream()
        .filter(n -> {
            System.out.println("filtering: " + n); // Этот вывод не появится здесь
            return n % 2 == 0;
        })
        .map(n -> n * 2);

// Терминальная операция запускает весь конвейер
List<Integer> result = stream.collect(Collectors.toList());
// Теперь в консоли появятся сообщения от filter

Распространённые терминальные операции: collect(), forEach(), reduce(), count(), anyMatch(), findFirst().