Что произойдет при повторном вызове операции на уже закрытом стриме в Java
Что проверяют
Понимаете ли вы, что Stream одноразовый, и отличаете ли «стрим уже потреблён» от «стрим закрыт через close()». Следом обычно спрашивают, какие стримы вообще нужно закрывать и как пройти по одним данным дважды.
Как отвечать
Любая повторная операция над стримом, который уже потреблён терминальной операцией или закрыт, бросает IllegalStateException с сообщением stream has already been operated upon or closed. Это касается и промежуточных операций: вызов filter или map на том же объекте тоже упадёт.
- терминальная операция:
forEach,collect,count,iterator()помечают конвейер использованным, ноclose()не вызывают и обработчикиonCloseне запускают; - промежуточная операция: возвращает новый стрим, а старый считается уже связанным. Код
s.filter(...); s.map(...)бросит исключение на втором вызове; close(): повторный вызов безопасен и ничего не делает. Нужен он только стримам, за которыми стоит ресурс:Files.lines,Files.list,Files.walk,Files.find. Их открывают в try-with-resources, иначе утекает файловый дескриптор. Стрим от коллекции закрывать не нужно;- повторный проход: храните не стрим, а его источник. Либо соберите результат в
Listи стройте новые стримы от него, либо держитеSupplier<Stream<T>>и вызывайтеget()на каждый проход.
Если интервьюер имел в виду потоки ввода-вывода, ответ другой: чтение из закрытого InputStream или BufferedReader обычно бросает IOException, а повторный close() по контракту Closeable ничего не делает.
Где спотыкаются
Говорят, что стрим закрывается сам после терминальной операции. Он становится непригодным, но onClose не срабатывает, и у стрима из Files.lines дескриптор останется открытым.
Предлагают «проверять состояние стрима перед вызовом». Публичного метода для такой проверки нет. Правильное решение: не хранить стрим в поле и не передавать его дальше после использования.
Путают Stream API с InputStream и отвечают про IOException, не уточнив, о каком стриме речь. Один уточняющий вопрос в начале экономит весь ответ.