Можно ли вызвать терминальную операцию несколько раз на одном потоке Stream в Java?

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

Ответ

Нет, после вызова терминальной операции поток (Stream) считается потребленным и закрывается. Повторная попытка выполнить любую операцию (промежуточную или терминальную) выбросит исключение IllegalStateException.

Почему поток одноразовый: Это дизайнерское решение, которое упрощает реализацию и предотвращает неопределенное поведение, так как многие потоки (например, чтение из файла или сетевого соединения) по своей природе являются одноразовыми.

Пример, демонстрирующий ошибку:

Stream<String> stream = Stream.of("A", "B", "C");

// Первый вызов терминальной операции — работает.
long count = stream.count();
System.out.println("Count: " + count); // Count: 3

// Второй вызов терминальной операции — исключение.
try {
    stream.forEach(System.out::println); // IllegalStateException!
} catch (IllegalStateException e) {
    System.out.println("Ошибка: поток уже закрыт.");
}

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

List<String> list = Arrays.asList("A", "B", "C");

// Создаем новый поток для каждой операции.
long count = list.stream().count();
list.stream().forEach(System.out::println);

// Или используем Supplier<Stream>
Supplier<Stream<String>> streamSupplier = () -> list.stream();
streamSupplier.get().count();   // OK
streamSupplier.get().forEach(System.out::println); // OK