Ответ
Обработка элементов в 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().