Reputation: 674
When Stream.concat is commented out, createLazyStream works as expected, it is initialized only when terminal operations are applied.
But if you uncomment Stream.concat line, then you will see that both streams were initialized even without actual usage (no terminal operations applied)
This is java bug, right? What is a workaround?
@Test
public void testConcat() {
Stream<Integer> stream = createLazyStream();
// Stream<Integer> result = Stream.concat(stream, createLazyStream());
}
private Stream<Integer> createLazyStream() {
return StreamSupport.stream(() -> {
System.out.println("initializing stream");
return IntStream.range(1,10).spliterator();
}, Spliterator.ORDERED, false);
}
Upvotes: 1
Views: 661
Reputation: 33855
The stream is not evaluated, just the lambda. This is done in the Constructor of ConcatSpliterator
, to test if the new stream is sized:
unsized = aSpliterator.estimateSize() + bSpliterator.estimateSize() < 0;
And to call estimateSize
, you need the spliterator, so it calls the lambda to get it.
You can see this by adding Thread.dumpStack()
to the lambda:
java.lang.Exception: Stack trace
at java.lang.Thread.dumpStack(Thread.java:1333)
at test.Main.lambda$0(Main.java:19)
at java.util.stream.StreamSpliterators$DelegatingSpliterator.get(StreamSpliterators.java:513)
at java.util.stream.StreamSpliterators$DelegatingSpliterator.estimateSize(StreamSpliterators.java:536)
at java.util.stream.Streams$ConcatSpliterator.<init>(Streams.java:713)
at java.util.stream.Streams$ConcatSpliterator$OfRef.<init>(Streams.java:781)
at java.util.stream.Stream.concat(Stream.java:1080)
at test.Main.main(Main.java:12)
In reality, your test is flawed. If you want to see if the stream is evaluated, you could add peek
before returning it.
return StreamSupport.stream(() -> {
return IntStream.range(1,10).peek(i -> System.out.println("peek")).spliterator();
}, Spliterator.ORDERED, false);
Now you will see that there is still no output when you uncomment that line.
It does seem like this is wrongly documented though (a 'bug' in the documentation). From the documentation of that StreamSupport.stream
method (Link):
The Supplier.get() method will be invoked on the supplier no more than once, and only after the terminal operation of the stream pipeline commences.
Upvotes: 6