Рубрики
Без рубрики

Исключение “Поток уже обработан или закрыт” в Java

Узнайте, как решить исключение “Поток уже обработан или закрыт” в Java.

Автор оригинала: baeldung.

1. Обзор

В этой краткой статье мы обсудим общее Исключение , с которым мы можем столкнуться при работе с классом Stream в Java 8:

IllegalStateException: stream has already been operated upon or closed.

Мы рассмотрим сценарии, когда возникает это исключение, и возможные способы его избежать, а также практические примеры.

2. Причина

В Java 8 каждый класс Stream представляет собой одноразовую последовательность данных и поддерживает несколько операций ввода-вывода.

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

Всякий раз, когда терминальная операция вызывается для объекта Stream , экземпляр потребляется и закрывается.

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

Давайте посмотрим, как это можно перевести на практический пример:

Stream stringStream = Stream.of("A", "B", "C", "D");
Optional result1 = stringStream.findAny(); 
System.out.println(result1.get()); 
Optional result2 = stringStream.findFirst();

В результате:

A
Exception in thread "main" java.lang.IllegalStateException: 
  stream has already been operated upon or closed

После вызова метода #findAny() поток строк закрывается, поэтому любая дальнейшая операция с потоком вызовет исключение IllegalStateException , и это произошло после вызова метода #findFirst () .

3. Решение

Проще говоря, решение состоит в создании нового Потока каждый раз, когда он нам нужен.

Мы, конечно, можем сделать это вручную, но именно здесь функциональный интерфейс Поставщик становится действительно удобным:

Supplier> streamSupplier 
  = () -> Stream.of("A", "B", "C", "D");
Optional result1 = streamSupplier.get().findAny();
System.out.println(result1.get());
Optional result2 = streamSupplier.get().findFirst();
System.out.println(result2.get());

В результате:

A
A

Мы определили объект поставщик потока с типом Поток<Строка> , который является точно таким же типом, который возвращает метод #get () . Поставщик основан на лямбда-выражении, которое не принимает входных данных и возвращает новый Поток .

Вызов функционального метода get() на Поставщике возвращает только что созданный Поток объект, над которым мы можем безопасно выполнить другую Потоковую операцию.

5. Заключение

В этом кратком руководстве мы рассмотрели, как выполнять терминальные операции с Потоком несколько раз, избегая при этом известного исключения IllegalStateException , которое возникает, когда Поток уже закрыт или обработан.

Вы можете найти полный исходный код и все фрагменты кода для этой статьи на GitHub .