“Stream has already been operated upon or closed” Exception in Java

1. Overview

In this brief article, we’re going to discuss a common Exception that we may encounter when working with the Stream class in Java 8:

IllegalStateException: stream has already been operated upon or closed.

We’ll discover the scenarios when this exception occurs, and the possible ways of avoiding it, all along with practical examples.

2. The Cause

In Java 8, each Stream class represents a single-use sequence of data and supports several I/O operations.

Stream should be operated on (invoking an intermediate or terminal stream operation) only once. A Stream implementation may throw IllegalStateException if it detects that the Stream is being reused.

Whenever a terminal operation is called on a Stream object, the instance gets consumed and closed.

Therefore, we’re only allowed to perform a single operation that consumes a Stream, otherwise, we’ll get an exception that states that the Stream has already been operated upon or closed.

Let’s see how this can be translated to a practical example:

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

As a result:

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

After the #findAny() method is invoked, the stringStream is closed, therefore, any further operation on the Stream will throw the IllegalStateException, and that’s what happened after invoking the #findFirst() method.

3. The Solution

Simply put, the solution consists of creating a new Stream each time we need one.

We can, of course, do that manually, but that’s where the Supplier functional interface becomes really handy:

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

As a result:

A
A

We’ve defined the streamSupplier object with the type Stream<String>, which is exactly the same type which the #get() method returns. The Supplier is based on a lambda expression that takes no input and returns a new Stream.

Invoking the functional method get() on the Supplier returns a freshly created Stream object, on which we can safely perform another Stream operation.

5. Conclusion

In this quick tutorial, we’ve seen how to perform terminal operations on a Stream multiple times, while avoiding the famous IllegalStateException that is thrown when the Stream is already closed or operated upon.

You can find the complete source code and all code snippets for this article over on GitHub.

Related posts:

New Stream Collectors in Java 9
Setting Up Swagger 2 with a Spring REST API
Java Program to Check Whether a Given Point is in a Given Polygon
Comparing Objects in Java
Java Program to Check Whether an Undirected Graph Contains a Eulerian Path
Java Program to Find the Longest Subsequence Common to All Sequences in a Set of Sequences
Java Program to Check whether Graph is Biconnected
Connect through a Proxy
Assertions in JUnit 4 and JUnit 5
Guide to Dynamic Tests in Junit 5
Adding a Newline Character to a String in Java
Concurrent Test Execution in Spring 5
Java Program to Implement Knapsack Algorithm
Java Program to Implement Stack using Linked List
Java Program to Perform Searching Based on Locality of Reference
Java Program to Check if a Given Binary Tree is an AVL Tree or Not
Spring Boot - Introduction
So sánh ArrayList và LinkedList trong Java
A Custom Media Type for a Spring REST API
Giới thiệu Java Service Provider Interface (SPI) – Tạo các ứng dụng Java dễ mở rộng
Handle EML file with JavaMail
A Quick JUnit vs TestNG Comparison
Java Program to Check if an UnDirected Graph is a Tree or Not Using DFS
Java Program to Implement Gaussian Elimination Algorithm
Giới thiệu luồng vào ra (I/O) trong Java
Java Program to Perform Inorder Non-Recursive Traversal of a Given Binary Tree
Java Program to Implement Hash Tables Chaining with Binary Trees
Request a Delivery / Read Receipt in Javamail
Spring Boot Configuration with Jasypt
Split a String in Java
Spring NoSuchBeanDefinitionException
Jackson JSON Views