2016-02-12 43 views
1

我想对一个数组做一个周期性总和,即一个索引模n上的和。Java 8流:阵列上的周期性总和

int size=100; 
double[] doubleArr = new double[size]; 
for (int i = 0; i < size; i++){ 
    doubleArr[i]=Math.random(); 
} 
int n=2; 
double[] results= new double[n]; 
for (int i = 0; i < doubleArr.length; i++) { 
    results[i % n] += doubleArr[i]; 
} 
System.out.println(Arrays.toString(results)); 

此代码有效,但由于我的数组非常庞大,我想要并行化操作。

Java 8流似乎是一个很好的解决方案。

double[] results2= new double[n]; 
IntStream.range(0, doubleArr.length).forEach(i -> results2[i % n] += doubleArr[i]); 
System.out.println(Arrays.toString(results2)); 

我得到了同样的结果。精细。

但是,如果我想并行化,它会失败。

double[] results3= new double[n]; 
IntStream.range(0, doubleArr.length).parallel().forEach(i ->  results3[i % n] += doubleArr[i]); 
System.out.println(Arrays.toString(results3)); 

我明白这是因为results3是可变的。

我想我应该在流操作中产生结果,有一个collect,但我不知道如何继续。

+0

它失败,例外或如何?如果抛出异常,则发出异常,如果结果不是预期的结果和期望后的结果 –

+0

“失败”是什么意思? – syntagma

+0

@ REACHUS最终数组是从多个线程编辑的,这会给出不准确的结果 – Ferrybig

回答

1

您可以从可能的modulos(0到n)的范围开始:

double[] result = IntStream.range(0, n) 
     .mapToDouble(i -> IntStream.rangeClosed(0, (size-i-1)/n) 
            .mapToDouble(j -> doubleArr[j*n+i]).sum()) 
     .toArray(); 

如果n是更核心的这个数字你,然后并联外流就足够了。如果不是,请尝试并行化内部流。

+0

It'works fine !!非常感谢 – xehyrofidd

+0

,但它比基本循环更慢:'( – xehyrofidd

+0

@xehyrofidd,对于size = 1_000_000并行,对我来说它更快(虽然加速并不是非常重要)。顺便说一句,如果你不需要Kahan求和, .sum()'与'.reduce(0,Double :: sum)'相比,它会更快。 –