4. 匯聚(Reduce)Stream
在介紹匯聚操作之前,我們先看一下Java doc中對於其定義: 匯聚操作(也稱爲摺疊)接受一個元素序列爲輸入,反覆使用某個合併操作,把序列中的元素合併成一個彙總的結果。比如查找一個數字列表的總和或者最大值,或者把這些數字累積成一個List對象。Stream接口有一些通用的匯聚操作,比如reduce()和collect();也有一些特定用途的匯聚操作,比如sum(),max()和count()。注意:sum方法不是所有的Stream對象都有的,只有IntStream、LongStream和DoubleStream是實例纔有。
可變匯聚:把輸入的元素們累積到一個可變的容器中,比如Collection或者StringBuilder;
其他匯聚:除去可變匯聚剩下的,一般都不是通過反覆修改某個可變對象,而是通過把前一次的匯聚結果當成下一次的入參,反覆如此。比如reduce,count,allMatch;
4.1 可變匯聚
可變匯聚對應的只有一個方法:collect,正如其名字顯示的,它可以把Stream中的要有元素收集到一個結果容器中(比如Collection)。先看一下最通用的collect方法的定義(還有其他override方法):
1 | <R> R collect(Supplier<R> supplier, |
2 | BiConsumer<R, ? super T> accumulator, |
3 | BiConsumer<R, R> combiner); |
先來看看這三個參數的含義:Supplier supplier是一個工廠函數,用來生成一個新的容器;BiConsumer accumulator也是一個函數,用來把Stream中的元素添加到結果容器中;BiConsumer combiner還是一個函數,用來把中間狀態的多個結果容器合併成爲一個(併發的時候會用到)。看暈了?來段代碼!
1 | List<Integer> nums = Lists.newArrayList( 1 , 1 , null , 2 , 3 , 4 , null , 5 , 6 , 7 , 8 , 9 , 10 ); |
2 | List<Integer> numsWithoutNull = nums.stream().filter(num -> num != null ). |
3 | collect(() -> new ArrayList<Integer>(), |
4 | (list, item) -> list.add(item), |
5 | (list1, list2) -> list1.addAll(list2)); |
上面這段代碼就是對一個元素是Integer類型的List,先過濾掉全部的null,然後把剩下的元素收集到一個新的List中。進一步看一下collect方法的三個參數,都是lambda形式的函數(*上面的代碼可以使用方法引用來簡化,留給讀者自己去思考*)。
但是上面的collect方法調用也有點太複雜了,沒關係!我們來看一下collect方法另外一個override的版本,其依賴[Collector](http://docs.oracle.com/javase/8/docs/api/java/util/stream/Collector.html)。
1 | <R, A> R collect(Collector<? super T, A, R> collector); |
這樣清爽多了!少年,還有好消息,Java8還給我們提供了Collector的工具類–[Collectors](http://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html),其中已經定義了一些靜態工廠方法,比如:Collectors.toCollection()收集到Collection中, Collectors.toList()收集到List中和Collectors.toSet()收集到Set中。這樣的靜態方法還有很多,這裏就不一一介紹了,大家可以直接去看JavaDoc。下面看看使用Collectors對於代碼的簡化:
1 | List<Integer> numsWithoutNull = nums.stream().filter(num -> num != null ). |
2 | collect(Collectors.toList()); |
原創文章,轉載請註明: 轉載自併發編程網 – ifeve.com本文鏈接地址: Java8初體驗(二)Stream語法詳解