count(), а потом collect() на том же стриме падает

Код выглядит безобидно: посчитали количество элементов стрима, а потом собрали их же в список. Запускаешь — и вместо списка получаешь исключение.

Stream в Java — одноразовый объект. Терминальная операция, в том числе count(), помечает стрим как использованный. Повторный вызов любой другой операции на этом же стриме — не «ещё один проход», а обращение к уже закрытому ресурсу.

Stream s = Stream.of(1, 2, 3) .peek(System.out::println);

long count = s.count(); List list = s.collect(Collectors.toList()); // IllegalStateException: // stream has already been operated upon or closed

Важная деталь: peek с побочным эффектом здесь может вообще не выполниться для count() — некоторые реализации Stream API оптимизируют count(), если знают размер источника заранее (например, у коллекции с известным size()), и не проходят по элементам вообще. Это отдельная ловушка: код с side effect в peek() ведёт себя непредсказуемо в зависимости от источника стрима.

Что спросят следом: как получить и количество, и содержимое корректно. Ответ — материализовать стрим один раз в List, а дальше считать size() и работать со списком, либо пересоздать стрим из той же коллекции отдельным вызовом stream(). Стрим не кэширует промежуточное состояние — он не структура данных, а одноразовый конвейер вычислений.

Stream — это не list, по которому можно пройтись дважды. Один стрим — одна терминальная операция, без исключений.

senior·base — что спрашивают на самом деле


В этом посте были ссылки, но мы их удалили по правилам Сетки