为了证明streams.generate(supplier).limit(N)
导致对supplier.get()
的调用超过N次,请考虑以下代码:
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
与预期的一样等于[0,1,...,N_ELEMENTS-1]
,但与预期相反,B
不包含与A
相同的元素。相反,b
通常包含大于或等于n_elements
的元素,这表示对供应商的调用次数多于n_elements
。
另一个例子是streams.generate(new Random(0)::nextdouble()).limit(5)
并不总是生成相同的一组数字。
流API不能保证intstream.generate()
调用生成器指定的次数。而且这个电话不尊重命令。
如果您确实需要一个数字递增的并行流,那么最好使用intstream.range(0,N_ELEMENTS).parallex()
。这不仅确保您实际上拥有从0
到n_elements-1
的所有数字,而且大大减少了争用并保证了顺序。如果需要生成更复杂的内容,可以考虑使用自定义源代码定义自己的拆分器类。
请注意,建议的intstream.iterate
解决方案可能并行化程度不高,因为它是按自然顺序的源代码。