1) How can I use a Supplier (supplier
) to create a sized stream of N values in parallel, while ensuring that no more than N calls are made to the supplier? I need this because I have a supplier with a costly supplier.get()
operation.
2) The 'obvious' answer to my question, Streams.generate(supplier).limit(N)
, does not work and often results in more than N calls being made to the supplier. Why is this?
As 'proof' of the fact that Streams.generate(supplier).limit(N)
results in more than N calls to supplier.get()
, consider the following code:
public class MWE {
static final int N_ELEMENTS=100000;
static Supplier<IntSupplier> mySupplier = () -> new IntSupplier() {
AtomicInteger ai = new AtomicInteger(-1);
@Override
public int getAsInt() {
return ai.incrementAndGet();
}
};
public static void main(String[] args) {
int[] a = IntStream.generate(mySupplier.get()).limit(N_ELEMENTS).toArray();
int[] b = IntStream.generate(mySupplier.get()).parallel().limit(N_ELEMENTS).toArray();
}
}
a
is equal to [0, 1, ..., N_ELEMENTS-1]
as expected, but contrary to what you might expect b
does not contain the same elements as a
. Instead, b
often contains elements that are greater than or equal to N_ELEMENTS
, which indicates more than N_ELEMENTS
number of calls to the supplier.
Another illustration would be that Streams.generate(new Random(0)::nextDouble()).limit(5)
does not always generate the same set of numbers.