«Поток уже оперирован или закрыт» Исключение в Java

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

1. обзор

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

IllegalStateException: stream has already been operated upon or closed.

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

2. Причина

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

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

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

Следовательно,we’re only allowed to perform a single operation that consumes a*Stream*, в противном случае мы получим исключение, в котором говорится, что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()stringStream закрывается, поэтому любая дальнейшая операция надStream будет вызыватьIllegalStateException, и это то, что произошло после вызова#findFirst() метод.

3. Решение

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

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

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

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

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

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

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

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