2017-01-21 54 views
3

Aggregating with Streams中,Brian Goetz比較填充使用Stream.collect()的集合,並且使用Stream.forEach()做同樣的,具有以下兩個片段:Stream.forEach()是否總是平行工作?

Set<String> uniqueStrings = strings.stream() 
            .collect(HashSet::new, 
              HashSet::add, 
              HashSet::addAll); 

而且,

Set<String> set = new HashSet<>(); 
strings.stream().forEach(s -> set.add(s)); 

然後他解釋說:

關鍵 區別在於,用forEach()版本,多個線程試圖訪問單個結果 容器同時,而與parallel collect(),每個線程有它自己的本地結果 容器,其結果合併後。

據我的理解,只有在流並行時,多個線程纔會在forEach()情況下工作。但是,在給出的示例中,forEach()在順序流上操作(不調用parallelStream())。

那麼,forEach()是否總是並行工作,或者代碼片段應該調用parallelStream()而不是stream()。 (或者我錯過了什麼?)

+0

順便說一句,在這個例子中,collect()並沒有在並行流上被調用。 (?) – ARX

回答

4

不,forEach()不平行如果流不平行。爲了討論的緣故,我認爲他簡化了這個例子。

作爲證據,該代碼是AbstractPipeline類的評價方法中(這是從的forEach調用)

return isParallel() 
       ? terminalOp.evaluateParallel(this, sourceSpliterator(terminalOp.getOpFlags())) 
       : terminalOp.evaluateSequential(this, sourceSpliterator(terminalOp.getOpFlags())); 
+1

感謝上帝。平行流意味着啓動一個線程池,這將是一個超級昂貴的隱藏操作! –

1

整體報價去如下:

正如可以並行安全提供減少組合功能是聯想性的並且沒有干擾性副作用,如果Stream.collect()符合某些簡單的一致性要求(在collect()的規範中概述),則易於安全並行化。

然後你報什麼:

的主要區別是,隨着forEach()版本,多個線程試圖同時訪問一個結果容器,而平行collect(),每個線程有自己的本地結果容器,其結果在之後合併。

由於第一句話講清楚並行的,我的理解是,無論forEach()collect()平行流的背景下說的。