2016-02-12 21 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)'相比,它會更快。 –