Java8 Stream

引入Stream:

注意:下面都是自己的理解,有什麼不對的歡迎指出,謝謝 (●'◡'●)

先來看一個例子:遍歷所有書籍Book的實體類(auther,price兩個屬性),找到名稱爲"zx"的書籍並返回

按照我們以前的思路來處理:

     /**
     * 遍歷書籍找到指定作者的書籍 並返回
     * @param books
     * @return
     */
    public static List<Book> filterAuth(List<Book> books){
        List<Book> filterResult = new ArrayList<>(); //保存過濾的數據
        for(Book b:books){
            if(b.getAuther().equals("zx")){//過濾條件
                filterResult.add(b);//保存到list中
            }
        }
        return  filterResult;
    }

用Stream API的方式來處理(對比上面的代碼 便捷且代碼量也省了很多奧(●'◡'●)):

在一次迭代中儘可能多的執行用戶指定的操作

 public static void main(String[] args) {
       List<Book> books = Arrays.asList(new Book("zx",80),new Book("chy",200),new Book("zx",200));

       //Stream API 處理  
       List<Book> result = books.stream().filter(b->b.getAuther().equals("zx")).collect(Collectors.toList());
}

下面我們來說Stream是如何做到的!

瞭解Stream

流(Stream)是Java API的新成員,它允許你以聲明性方式處理數據集合(通過查詢語句來表達,而不 是臨時編寫一個實現)。

流的使用

一般包括三件事: 

        一個數據源(如集合)來執行一個查詢; 

        一箇中間操作鏈,形成一條流的流水線; 

       一個終端操作,執行流水線,並能生成結果。 

Stream接口定義了許多操作。它們可以分爲兩大類:

           中間操作:中間操作會返回一個流,並可以鏈接在一起。可以用它們來設置一條流 水線,但並不會生成任何結果。 

                         無狀態(stateless)操作:該操作的數據不收上一步操作的影響,如filter map

                        有狀態(s'ta'te'fu)操作:必須等上一步操作完拿到全部元素後纔可操作,如sorted

           終端操作:觸發數據的流動,並收集結果

                        短路操作:不用處理全部元素就可以返回結果,類似於break,如anyMatch findFirst

                        非短路操作:會遍歷所有元素,如collect max

Stream採用某種方式記錄用戶每一步的操作,當用戶調用終止操作時將之前記錄的操作疊加到一起,儘可能地在一次迭代中全部執行掉

Stream的example(直接來例子,不然太難理解了)

example1.中間操作只是對操作進行了記錄/標記,並不會觸發該操作

 /**
         * example1.中間操作只是對操作進行了記錄,並不會觸發/執行 操作
         */
        books.stream().filter(b->{
           if(b.getAuther().equals("zx")){
               System.out.println("我是中間操作,並返回作者名稱:"+b.getAuther());
               return true;
           }
           return false;
        });

控制檯:什麼都沒有打印,但是進了filter方法 並做了記錄,只是沒有觸發方法,驗證了中間操作只是記錄,並不會觸發

example2.結束操作

        /**
         * example2.結束操作
         */
        books.stream().filter(b->{
            if(b.getAuther().equals("zx")){
                System.out.println("我是中間操作,並返回作者名稱:"+b.getAuther());
                return true;
            }
            return false;
        }).forEach(b->System.out.println("我是結束操作,並返回作者的名稱"+b.getAuther()));

控制檯返回:只有結束操作纔會觸發實際的計算(也就是說只有遇到結束操作的時候纔會調用方法(⊙﹏⊙))

example3.多箇中間操作

        /**
         * example.3 多箇中間操作
         */

        books.stream().filter(b->{
            if(b.getAuther().equals("zx")){
                System.out.println("我是中間操作FilterStage,返回名稱"+b.getAuther());
                return true;
            }
            return false;
        }).map(b->{
            System.out.println("我是中間操作mapStage,返回名稱"+b.getAuther());
            return b.getPrice();
        }).forEach(b->System.out.println("我是結束操作"+b+"\n"));

控制檯:由此我們可以推斷出結束操作的流程:執行forEach循環操作的時候 會往前追溯到它的上一步中間操作(mapStage),上一步中間操作又會追溯到上上一步中間操作(filterStage),直到上上一步中間操作前面已經沒有中間操作了,開始自上向下開始執行!第二次循環亦如此,由此我們可以引出下面Stage與pipeline的關係

 

沒錯!到了這裏,我們就有疑問,操作是怎麼存儲的呢?是什麼方式存儲的呢?結束操作是怎麼觸發這些方法的呢?下面我們就根據源碼一一解讀

關係圖 Stage  pipeline(流水線)

 

貼出類圖

 

未完待續。。。。。

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章