java8之Stream API(從迭代器到Stream操做)

當你處理集合時,一般會迭代全部元素並對其中的每個進行處理。例如,假設咱們但願統計一個文件中的全部長單詞: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操做符不會改變源對象。相反,它們會返回一個持有結果的新Streamorm

  • 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的元素。

相關文章
相關標籤/搜索