GotchaDifficulty: Advanced1 min

Why a Stream Cannot Be Used Twice

A stream kept in a variable, counted, then collected, and an exception about a state nobody set.

A stream can run one terminal operation (the last step, which produces a result and makes the stream run) and no more. A second one throws IllegalStateException, because the stream holds a way of pulling elements from its source, not the elements themselves, and the first operation used it up.

A stream stored in a variable so it can be counted and then collected:

java
Stream<Invoice> big = invoices.stream().filter(i -> i.pence() > 10_000);

long howMany = big.count();
List<Invoice> list = big.toList();
text
Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closed

A stream is not a collection. It does not hold the elements; it holds a way of pulling them from a source, and once the terminal operation has pulled them the stream has nothing left to give.

That is exactly why the source can be a file, a network response or an infinite generator. A thing that could be replayed would have to remember everything it produced.

What to do when you need two results
You wantDo
Two results from one passCollect once, then work on the collection
Two independent pipelinesCall .stream() on the source twice
A count and the elementsCollect to a list and call size()

The habit that avoids all of it: do not store a stream in a variable. Build it, use it and end it in one expression, and the question never comes up.