引入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(流水線)
貼出類圖
未完待續。。。。。