Java8 Stream reduce操作

Reduce,顧名思義爲減少的意思,就是根據指定的計算模型將Stream中的值計算得到一個最終結果。在之前的一篇文章Java8函數式編程中簡單介紹,Stream的count、min 和max方法底層都是依賴reduce實現的,本篇文章將簡單介紹一下Java8 Stream reduce的幾種基本用法。

首先來看一下Reduce三種形式:
S.N.     方法說明
1     Optional<T> reduce(BinaryOperator<T> accumulator);
       對Stream中的數據通過累加器accumulator迭代計算,最終得到一個Optional對象
2     T reduce(T identity, BinaryOperator<T> accumulator);
       給定一個初始值identity,通過累加器accumulator迭代計算,得到一個同Stream中數據同類型的結果
3     <U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner);
       給定一個初始值identity,通過累加器accumulator迭代計算,得到一個identity類型的結果,第三個參數用於使用並行     流時合併結果


1. Optional<T> reduce(BinaryOperator<T> accumulator);

首先看一下函數式接口BinaryOperator,繼承於BiFunction,Bifunction中有一個apply方法,接收兩個參數,返回一個結果。如下:

    @FunctionalInterface
    public interface BinaryOperator<T> extends BiFunction<T,T,T> {
    }
     
    @FunctionalInterface
    public interface BiFunction<T, U, R> {
        R apply(T t, U u);
    }

也就是說,reduce(BinaryOperator<T> accumulator)方法需要一個函數式接口參數,該函數式接口需要兩個參數,返回一個結果(reduce中返回的結果會作爲下次累加器計算的第一個參數),也就是所講的累加器。所以reduce(BinaryOperator<T> accumulator)方法可以如下調用:

   

 @Test
    public void reduceTest() {
        Optional accResult = Stream.of(1, 2, 3, 4)
                .reduce((acc, item) -> {
                    System.out.println("acc : " + acc);
                    acc += item;
                    System.out.println("item: " + item);
                    System.out.println("acc+ : " + acc);
                    System.out.println("--------");
                    return acc;
                });
        System.out.println(accResult);
    }

運行結果:

    acc : 1
    item: 2
    acc+ : 3
    --------
    acc : 3
    item: 3
    acc+ : 6
    --------
    acc : 6
    item: 4
    acc+ : 10
    --------
    Optional[10]

2. T reduce(T identity, BinaryOperator<T> accumulator);

提供一個跟Stream中數據同類型的初始值identity,通過累加器accumulator迭代計算Stream中的數據,得到一個跟Stream中數據相同類型的最終結果,可以如下調用:

  @Test
    public void reduceTest1() {
        int accResult = Stream.of(1, 2, 3, 4)
                .reduce(100, (acc, item) -> {
                    System.out.println("acc : "  + acc);
                    acc += item;
                    System.out.println("item: " + item);
                    System.out.println("acc+ : "  + acc);
                    System.out.println("--------");
                    return acc;
                });
        System.out.println(accResult);
    }

運行結果:

    acc : 100
    item: 1
    acc+ : 101
    --------
    acc : 101
    item: 2
    acc+ : 103
    --------
    acc : 103
    item: 3
    acc+ : 106
    --------
    acc : 106
    item: 4
    acc+ : 110
    --------
    110

3. <U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner);

首先看一下BiFunction的三個泛型類型分別是U、 ? super T、U,參考BiFunction函數式接口apply方法定義可以知道,累加器累加器通過類型爲U和? super T的兩個輸入值計算得到一個U類型的結果返回。也就是說這種reduce方法,提供一個不同於Stream中數據類型的初始值,通過累加器規則迭代計算Stream中的數據,最終得到一個同初始值同類型的結果。看一個調用示例:

 

   @Test
    public void reduceTest2() {
        ArrayList<Integer> accResult_ = Stream.of(2, 3, 4)
                .reduce(Lists.newArrayList(1),
                        (acc, item) -> {
                            acc.add(item);
                            System.out.println("item: " + item);
                            System.out.println("acc+ : " + acc);
                            System.out.println("BiFunction");
                            return acc;
                        }, (acc, item) -> {
                            System.out.println("BinaryOperator");
                            acc.addAll(item);
                            System.out.println("item: " + item);
                            System.out.println("acc+ : " + acc);
                            System.out.println("--------");
                            return acc;
                        }
                );
        System.out.println("accResult_: " + accResult_);
    }

運行結果:

    item: 2
    acc+ : [1, 2]
    BiFunction
    item: 3
    acc+ : [1, 2, 3]
    BiFunction
    item: 4
    acc+ : [1, 2, 3, 4]
    BiFunction
    accResult_: [1, 2, 3, 4]

通過運行結果可以看出,第三個參數定義的規則並沒有執行。這是因爲reduce的第三個參數是在使用parallelStream的reduce操作時,合併各個流結果的,本例中使用的是stream,所以第三個參數是不起作用的。上述示例,提供一個只有一個元素1的arrayList,通過累加器迭代,將stream中的數據添加到arrayList中。

以上就是stream中reduce的三種用法,用來通過特定的規則計算stream中的值,得到一個最終結果,其實還是很簡單的。推薦一篇剛看到的講解Java8 Stream的文章,Java Stream 詳解,我陸陸續續也寫了好幾篇關於Java8新特性的文章了,但是比較下來並沒有上面那篇文寫的那麼體系,之後的文章可以借鑑一下那篇文章的組織方法。

參考鏈接:

    1. Java 8系列之Stream中萬能的reduce
    2. Java8初體驗(二)Stream語法詳解
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章