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新特性的文章了,但是比較下來並沒有上面那篇文寫的那麼體系,之後的文章可以借鑑一下那篇文章的組織方法。
參考鏈接: