上节介绍了将流转成集合的方法(toCollections)和将元素转换成拼接字符串(joining)的方法,本节介绍几个求统计数值的方法,分别是
- counting
- maxBy
- minBy
- summingInt/summingLong/summingDouble
- averagingInt/averagingLong/averagingDouble
- reducing
前三个都是借助reducing方法来实现的,后面的两个方法的实现思路和reducing很像,所以这节先介绍reducing铺垫一下
1.reducing
reducing方法可以将流中的元素进行累加,运算到第n个元素的时候,将前n-1个元素运算的中间结果和第n个元素进行运算,这个方法有三个重载
1.1reducing(T identity, BinaryOperator op)
这个方法接受两个参数,一个是初始值,如果流中的元素都没有的时候就会返回这个identity,另一个参数是BinaryOperator,这个是指定具体做什么运算
比如下面这个reduce的用法可以计算流中所有元素的总和
int total = IntStream.range(0, 10).reduce(0, Integer::sum);
返回的类型是Collector<T, ?, T>,即流中的元素和最终输出的元素是同一个类型T,中间容器的类型可以是任意
这个方法的源码是:
具体实现是:
return new CollectorImpl<>(
boxSupplier(identity),
(a, t) -> {
a[0] = op.apply(a[0], t); },
(a, b) -> {
a[0] = op.apply(a[0], b[0]); return a; },
a -> a[0],
CH_NOID);
可以看到,它借助了一个长度为1的数组来作为中间的结果容器,这个的方法boxSupplier其实是提供这个数组,它的实现是:
private static <T> Supplier<T[]> boxSupplier(T identity) {
return () -> (T[]) new Object[] {
identity };
}
只是提供了一个类型为T的长度为1的数组,数组里面的元素是identity,也就是传入的第一个参数,这个collector具体的组成是
supplier | accumulator | combiner | finisher | characteristic |
---|---|---|---|---|
boxSupplier(identity) | (a, t) -> { a[0] = op.apply(a[0], t); }, | (a, b) -> { a[0] = op.apply(a[0], b[0]); return a; } | a -> a[0] | CH_NOID |
长度为1,类型为T,初始值为identity的数组 | 是将当前的元素T和中间结果a[0]进行运算之后再重新赋值到a[0] | 对于两个结果装着中间结果的数组,将他们的值进行 |