Запустится ли выполнение стрима в Java без вызова терминальной операции?

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

Ответ

Нет, не запустится. Стримы в Java реализуют ленивые вычисления (lazy evaluation).

  • Промежуточные операции (например, filter(), map(), sorted()) только конструируют конвейер обработки, но не обрабатывают данные.
  • Терминальная операция (например, collect(), forEach(), count()) инициирует фактическое выполнение всего конвейера, начиная от источника данных.

Пример, демонстрирующий ленивость:

List<String> list = List.of("a", "b", "c");

// Создание конвейера (ничего не выводится)
Stream<String> stream = list.stream()
    .peek(s -> System.out.println("До фильтра: " + s))
    .filter(s -> {
        System.out.println("Фильтр: " + s); // Этот код не выполнится сейчас
        return s.startsWith("a");
    })
    .map(String::toUpperCase);

System.out.println("Конвейер построен. Терминальной операции еще нет.");

// Только ВЫЗОВ терминальной операции запускает выполнение:
List<String> result = stream.collect(Collectors.toList());
// Теперь в консоли появятся все отладочные сообщения.

Почему это важно: Ленивость позволяет оптимизировать работу, например, избегать обработки всех элементов, если результат уже найден (findFirst()).