爲了練習Java 8流,我嘗試將下面的嵌套循環轉換爲Java 8流API。它計算^ B的最大數字和(A,B < 100),並採取〜0.135s我的酷睿i5 760Java 8與流和性能的嵌套循環
public static int digitSum(BigInteger x)
{
int sum = 0;
for(char c: x.toString().toCharArray()) {sum+=Integer.valueOf(c+"");}
return sum;
}
@Test public void solve()
{
int max = 0;
for(int i=1;i<100;i++)
for(int j=1;j<100;j++)
max = Math.max(max,digitSum(BigInteger.valueOf(i).pow(j)));
System.out.println(max);
}
我的解決方案,我預計會更快,因爲的paralellism居然拿了快閃(0.19s沒有parallel()
):
int max = IntStream.range(1,100).parallel()
.map(i -> IntStream.range(1, 100)
.map(j->digitSum(BigInteger.valueOf(i).pow(j)))
.max().getAsInt()).max().getAsInt();
我的問題
- 沒有我做轉換權或是否有更好的辦法ŧ o將嵌套循環轉換爲流計算?
- 爲什麼流的變體比舊的慢?
- 爲什麼parallel()語句實際上將時間從0.19s增加到0.25s?
我知道microbenchmarks是脆弱的,並行度只是值得的大問題,但對於一個CPU,即使0.1s是永恆的,對吧?
更新
我在Eclipse開普勒JUnit的4個構架測量(它示出了採取用於執行測試的時間)。
我的結果爲A,B < 1000而不是100:
- 傳統循環186s
- 順序流193S
- 並行流55S
更新2 更換sum+=Integer.valueOf(c+"");
與sum+= c - '0';
(感謝彼得!)削減了整整10秒並行方法,使其達到45秒。沒想到會有如此大的性能影響!另外,降低CPU核心數(在我的情況下爲4)的並行性並沒有太大的作用,因爲它只將時間減少到44.8s(是的,它增加了a和b = 0,但我認爲這贏得了對性能影響不大):
int max = IntStream.range(0, 3).parallel().
.map(m -> IntStream.range(0,250)
.map(i -> IntStream.range(1, 1000)
.map(j->.digitSum(BigInteger.valueOf(250*m+i).pow(j)))
.max().getAsInt()).max().getAsInt()).max().getAsInt();
你如何衡量?正如你指出的那樣,如果沒有適當的照顧,微基準的結果可能會產生誤導。 – assylias
我會用'sum + = c - '0'來代替'sum + = Integer.valueOf(c +「」);'',因爲這樣會快得多。 –
FWIW你可以使用'CharSequence.chars()'方法用'stream'代替'digitSum'中的循環。它避免了分配char數組。 –