For some reason Java Stream generates more values (calls hasNext() and next() methods of iterator.
Here's the synthetic example.
I have a generator in a form of an Iterator:
@RequiredArgsConstructor
static class TestIterator implements Iterator<Integer> {
private final int bound;
private final Random rnd = new Random();
private int current = 0;
@Override public boolean hasNext() {
return current < bound;
}
@Override public Integer next() {
current = rnd.nextInt(20);
System.out.println("Generated: " + current);
return current;
}
}
Now, I'm trying to have a flattened Stream which consists of few Iterators
public static void main(String... args) {
List<Iterator<Integer>> iterators = asList(
new TestIterator(18),
new TestIterator(18),
new TestIterator(18));
Stream<Integer> streams = iterators.stream()
.map(iter -> (Iterable<Integer>) () -> iter)
.flatMap(iter -> StreamSupport.stream(iter.spliterator(), false)) // <-- Here the stream of streams is flatten to a single stream of integers and 'parallel' is set to false
.limit(5); // <-- Here the limit is set
streams.forEach(i -> System.out.println("***Consumed: " + i));
}
And, surprisingly for me, the output is following:
Generated: 1
***Consumed: 1
Generated: 19
***Consumed: 19
Generated: 7
***Consumed: 7
Generated: 7
***Consumed: 7
Generated: 7
***Consumed: 7
Generated: 4
Generated: 3
Generated: 8
Generated: 14
Generated: 0
Generated: 16
Generated: 10
Generated: 3
Generated: 19
So, Stream generates more results than passed to the consumer in forEach. Even despite it's explicitly set 'parallel = false'.
In my real-world scenario hasNext() and next() functions are very expensive, taking data from external services.
Can anybody explain how to do a better job on limiting results?
Thanks in advance.