Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 8 Stream IllegalStateException: Stream has already been operated on or closed

I'm trying to generate Order instances using the Stream API. I have a factory function that creates the order, and a DoubleStream is used to initialize the amount of the order.

private DoubleStream doubleStream = new Random().doubles(50.0, 200.0);

private Order createOrder() {
    return new Order(doubleStream.findFirst().getAsDouble());
}

@Test
public void test() {

Stream<Order> orderStream = Stream.generate(() -> {
    return createOrder();
});

orderStream.limit(10).forEach(System.out::println);

If I initialize the Order instance using a literal (1.0), this works fine. When I use the doubleStream to create a random amount, the exception is thrown.

like image 564
Ole Avatar asked Jan 16 '15 18:01

Ole


2 Answers

The answer is in the javadoc of Stream (emphases mine):

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.

And in your code, you do use the stream twice (once in createOrder() and the other usage when you .limit().forEach()

like image 95
fge Avatar answered Oct 11 '22 18:10

fge


As said in other answers, Streams are single-use items and you have to create a new Stream each time you need one.

But, after all, this isn’t complicated when you remove all your attempts to store intermediate results. Your entire code can be expressed as:

Random r=new Random(); // the only stateful thing to remember

// defining and executing the chain of operations:
r.doubles(50.0, 200.0).mapToObj(Order::new).limit(10).forEach(System.out::println);

or even simpler

r.doubles(10, 50.0, 200.0).mapToObj(Order::new).forEach(System.out::println);
like image 37
Holger Avatar answered Oct 11 '22 17:10

Holger