stream流的归约
stream流的归约
stream流的归约是将stream流中的元素聚合,类似约sql的聚合。归约属于stream流的终端操作。
终端操作的注意点:
- stream流没有终端操作不会处理任何数据,没有终端操作的stream流很大可能是个bug!
- stream流只能有一个终端操作,并且不能再次重用该stream流,否则会抛出
IllegalStateException
异常
使用BinaryOperator
二元操作对stream流归约
需要注意2点
-
stream流可以通过
parallel()
进行并行计算 -
BinaryOperator
应该具有associativity(结合律,关联性)
A = B ⋃ C ⇒ R e d ( A ) = R e d ( R e d ( B ) , R e d ( C ) ) A = B ⋃ C ⇒ Red(A) = Red(Red(B), Red(C)) A=B⋃C⇒Red(A)=Red(Red(B),Red(C))
BinaryOperator
归约中的identity element(单位元,即 i op a = a op i = a,i为单位元)
探索Stream API中的归约方法
reduce()
有单位元的归约
List<Integer> ints = List.of(3, 6, 2, 1);
BinaryOperator<Integer> sum = (a, b) -> a + b;
int identity = 0;
int result = identity;
for (int i: ints) {
result = sum.apply(result, i);
}
System.out.println("sum = " + result);
使用reduce()
Stream<Integer> ints = Stream.of(0, 0, 0, 0);
int sum = ints.reduce(10, (a, b) -> a + b);
System.out.println("sum = " + sum);
结果
sum = 10
没有单位元的归约
Stream<Integer> ints = Stream.of(2, 8, 1, 5, 3);
Optional<Integer> optional = ints.reduce((i1, i2) -> i1 > i2 ? i1: i2);
if (optional.isPresent()) {
System.out.println("result = " + optional.orElseThrow());
} else {
System.out.println("No result could be computed");
}
结果
result = 8
在一个方法中融合映射合归约
<U> U reduce(U identity,
BiFunction<U, ? super T, U> accumulator,
BinaryOperator<U> combiner);
示例
Stream<String> strings = Stream.of("one", "two", "three", "four");
BinaryOperator<Integer> combiner = (length1, length2) -> length1 + length2;
BiFunction<Integer, String, Integer> accumulator =
(partialReduction, element) -> partialReduction + element.length();
int result = strings.reduce(0, accumulator, combiner);
System.out.println("sum = " + result);
结果
sum = 15
示意图