※ 引述《eieio (好多目標)》之銘言:
: 佳的寫法。慢五倍的關鍵並不是 stream,而是 boxing/unboxing
: integers.stream().reduce(...)
: integers.stream().mapToInt(Integer::intValue).reduce(...)
: 上面兩個寫法,有先 mapToInt 就可以避免掉過多的 boxing/unboxing,速度
: 跟 for loop 差不多。
: 同樣的道理,下面這段 code 很不好:
: String r = "";
: for (String s : strs) {
: r = r + s;
: }
: 上面這段 code,每次 r = r + s 就會產生一個新的 String,效能會很低。
: 要避免產生無用的 String,要用 StringBuilder。
http://openhome.cc/Gossip/Programmer/Parallel.html
Doug Lea在〈Stream Parallel Guidance〉文件中給了一些建議,對於
S.parallelStream().operation(F),如果N為S的元素數量,而Q為F處理每個元素的成本
,可以大略使用F中的操作或行數來計算,如果N*Q至少超過10000,才有平行化的價值。
因此,如果操作簡單如x -> x + 1,那麼至少得有10000個以上的元素,才有平行化的價
值,相對地,如果每個元素涉及大量運算,那麼就越有平行化的價值。
在Java上得考量一種處理成本:基本資料型態與對應的包裹器型態間的轉換。例如,int
與Integer之間的Boxing與Unboxing操作。如果實際上List中都是數值且進行數學運算,
考慮使用mapToInt轉為專屬於int的IntStream,而後再進行數學運算,可免去不必要的
Boxing與Unboxing成本。目前就JDK8的Stream程式庫來說,也不建議對I/O做平行處理。
在想要免於I/O、同步處理等待之類情況下,其他並行、非同步I/O程式庫或
CompletableFuture會是比較好的選擇。
資料來源的結構也是一個考量,先前談過,可思考將有序打為無序後,是否對平行處理有
益,另一方面,因為平行處理必須分而治之,在這之前採取易於劃分的資料結構作為來源
,對平行處理會有幫助,例如支援隨機存取的陣列、ArrayList或具有一定範圍的
IntStream.range,平行處理時會比較有效率;而HashSet、TreeSet等,因為涉及雜湊空
間與樹平衡等考量,會是其次之選;然而,像是LinkedList這類鏈結資料,走訪劃分資料
的成本是O(N),就不適合作為平行處理的來源結構,長度無法確定的資料來源,像是
Streams.iterate、BufferedReader.lines等,也不建議採用。