Win a copy of Microservices in Action this week in the Web Services forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Bear Bibeault
  • Devaka Cooray
  • Liutauras Vilda
  • Jeanne Boyarsky
Sheriffs:
  • Knute Snortum
  • Junilu Lacar
  • paul wheaton
Saloon Keepers:
  • Ganesh Patekar
  • Frits Walraven
  • Tim Moores
  • Ron McLeod
  • Carey Brown
Bartenders:
  • Stephan van Hulst
  • salvin francis
  • Tim Holloway

IllegalStateException: stream has already been operated upon or closed  RSS feed

 
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If we use a terminal operator on a stream then it is considered to be closed. We can't use it again. But why am I getting the following error on non-terminal operator?



java.lang.IllegalStateException: stream has already been operated upon or closed
 
Marshal
Posts: 61805
193
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Please use a bitOfSpaceAroundYourOperators. It is difficult to read -> and % without spaces.
Adding this discussion to the Java8 forum.


By the time you have finished line 6, you have got to the end of the first Stream. It is not possible to wind it back to its beginning in line 7, so you will suffer an exception.
 
Campbell Ritchie
Marshal
Posts: 61805
193
  • Likes 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You can't even run half a Stream and come back to it. You would have thought you could get the even natural numbers ≥ 100 like this:-. . . but you can't.

The idea of a Stream is that it is not a container nor a data structure. The IntStream in your example doesn't contain 0, 1, 2, 3...10. It processes those numbers. Once it has processed those numbers it is regarded as exhausted, and it cannot go back to the start of its source. Remember that source might be keyboard input if you use a BufferedReader or Scanner reading from System.in (look at these methods: 1, 2 (No. 2 is overloaded) and 3). If you have processed the input via one of those Streams, you cannot go back to the beginning and review the input as you would with a List. Streams are therefore intended to be single‑use objects. That is why most people don't assign Streams to identifiers in the first place if they can avoid it.
 
Viraj Bhosle
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks for the response. This is the point that makes it clear to me "it cannot go back to the start of its source".  
Can we really say that stream is exhausted at the line 6?? Because stream evaluation is lazy and it actually starts processing when a terminal operation is called.
 
Campbell Ritchie
Marshal
Posts: 61805
193
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Viraj Bhosle wrote:Thanks for the response. . . .

That's a pleasure

Can we really say that stream is exhausted at the line 6?? Because stream evaluation is lazy and it actually starts processing when a terminal operation is called.

Good point. I said, “regarded as exhausted,” so let's look on that as the Stream becoming even lazier . A Stream is intended to run through its source once and once only. It must have some sort of flag turned on whenever one of its methods is called, marking it as already used, and it will throw an Exception if any other methods are called, even if it hasn't processed any elements because it lacks a terminal operation. I tried it on JShell and got the same exception, until I tried this:-So obviously toString doesn't throw that exception.
 
Campbell Ritchie
Marshal
Posts: 61805
193
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
This appears in the documentation for Stream:-

A stream should be operated on (invoking an intermediate or terminal stream operation) only once. This rules out, for example, "forked" streams, where the same source feeds two or more pipelines, or multiple traversals of the same stream. A stream implementation may throw IllegalStateException if it detects that the stream is being reused. However, since some stream operations may return their receiver rather than a new stream object, it may not be possible to detect reuse in all cases.

Note it includes intermediate operations. That would of course exclude toString() which doesn't count as a Stream operation at all.
 
Viraj Bhosle
Greenhorn
Posts: 6
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

This rules out, for example, "forked" streams


That explains it.  Yes it may have some internal flag. Crystal clear now! Thanks!
 
It is sorta covered in the JavaRanch Style Guide.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!