當你處理集合時,一般會迭代全部元素並對其中的每個進行處理。例如,假設咱們但願統計一個文件中的全部長單詞:java
package java8test; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Arrays; import java.util.List; public class T5 { public static void main(String[] args) { try { String contents = new String(Files.readAllBytes( Paths.get("/home/fuhd/work/workspace/javaee/wwos.platform/pom.xml")), StandardCharsets.UTF_8); List<String> words = Arrays.asList(contents.split("\n")); //進行迭代 int count = 0; for(String w: words){ if(w.length() > 12) count++; } System.out.println(count); } catch (IOException e) { e.printStackTrace(); } } }
這裏面有什麼錯誤嗎?其實沒有——只是它很難被並行計算。這也是java8引入大量操做符的緣由。在Java8中,實現相同功能的操做符以下所示:優化
package java8test; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Arrays; import java.util.List; public class T5 { public static void main(String[] args) { try { String contents = new String(Files.readAllBytes( Paths.get("/home/fuhd/work/workspace/javaee/wwos.platform/pom.xml")), StandardCharsets.UTF_8); List<String> words = Arrays.asList(contents.split("\n")); //注意這一句 long count = words.stream().filter(w -> w.length() > 12).count(); System.out.println(count); } catch (IOException e) { e.printStackTrace(); } } }
stream方法會爲單詞列表生成一個Stream。filter方法會返回另外一個只包含單詞長度大於12的Stream。count方法會將Stream化簡爲一個結果。spa
一個Stream表面上看與一個集合很相似,容許你改變和獲取數據。可是實際上它與集合是有很大區別的:線程
Stream本身不會存儲元素。元素可能被存儲在底層的集合中,或者根據須要產生出來。code
Stream操做符不會改變源對象。相反,它們會返回一個持有結果的新Stream。orm
Stream操做符多是延遲執行的。這意味着它們會等到須要結果的時候才執行。xml
許多人發現Stream表達式比循環的可讀性更好。此外,它們還很容易進行並行執行。如下是一段如何並行統計長單詞的代碼:對象
package java8test; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Arrays; import java.util.List; public class T5 { public static void main(String[] args) { try { String contents = new String(Files.readAllBytes( Paths.get("/home/fuhd/work/workspace/javaee/wwos.platform/pom.xml")), StandardCharsets.UTF_8); List<String> words = Arrays.asList(contents.split("\n")); //注意這一句,stream()改爲了parallelStream()方法 long count = words.parallelStream().filter(w -> w.length() > 12).count(); System.out.println(count); } catch (IOException e) { e.printStackTrace(); } } }
只要將stream()方法改爲parallelStream方法,就可讓Stream API並行執行過濾和統計操做。get
Stream遵循「作什麼,而不是怎麼去作」的原則。在咱們的示例中,描述了須要作什麼:得到長單詞並對它們的個數進行統計。咱們沒有指定按照什麼順序,或者在哪一個線程中作,它們都是理所應當發生的。相反,循環在一開始就須要指定如何進行計算,所以就失去了優化的機會。it
當你使用Stream時,你會經過三個階段來創建一個操做流水線:
建立一個Stream。
在一個或多個步驟中,指定將初始Stream轉換爲另外一個Stream的中間操做。
使用一個終止操做來產生一個結果。該操做會強制它以前的延遲操做當即執行。在這以後,該Stream就不會再被使用
在咱們的示例中,經過stream或者parallelStream方法來建立Stream,再經過filter方法對其進行轉換,而count就是終止操做
注意:Stream操做不會按照元素的調用順序執行。在咱們的例子中,只有在count被調用的時候纔會執行Stream操做。當count方法須要第一個元素時,filter方法會開始請求各個元素,直到找到一個長度大於12的元素。