Collectors.averagingDouble()
Java 8
流的新类java.util.stream.Collectors
实现了java.util.stream.Collector
接口,同时又提供了大量的方法对流 (stream
) 的元素执行map
and
reduce
操作,或者统计操作。
Collectors.averagingDouble()
方法将流中的所有元素视为 double
类型并计算他们的平均值。该方法返回的是同一个 Collectors
实例,因此可以进行链式操作。
Collectors.averagingDouble()
接受一个参数,这个参数是一个 lambda
表达式,用于对所有的元素执行一个 map
操作。
Java
所有集合的 stream().collect()
可以接受一个收集器实例作为其参数并返回该收集器的计算结果
例如下面的代码,collect()
方法会把所有的元素收集起来然后传递给 Collectors.averagingDouble(d->d*2)
收集器,对每个元素执行 *2
操作后计算平均值
@Test
public void AveragingDoubleExample() {
List<Integer> list = Arrays.asList(1, 2, 3, 4);
Double result = list.stream().map(s -> {
System.out.println("map-> " + s);
return s;
}).collect(Collectors.averagingDouble(d -> {
System.out.println(d + "-->" + d * 2);
return d * 2;
})
);
System.out.println(result);
}
运行结果: 结果显示计算平均值时为什么会打印两遍其中的值?
- 如果在方法体中操作全局变量岂不是操作两遍?? 这不是坑么
- 如果在方法体中做复杂操作,岂不是两倍??? 巨坑阿
- 如果在方法体中做判断,判断后改动状态值,改两遍!!
- ……
- 用我智慧的大脑一想……没得玩了
map-> 1
1-->2
1-->2
map-> 2
2-->4
2-->4
map-> 3
3-->6
3-->6
map-> 4
4-->8
4-->8
5.0
为什么会这样打印两遍值?
-
详细对比了一下map,并打印相应的值
- 结论: 只打印一遍,说明流式操作只进行一次流式操作,排除map以及之前操作
-
collect
是一个收集器,收集传输过来的元素,并没有实际作用- 联想
Collectors.toList()
推断出没有重复的值 - 观察源码发现,其实际上就是
container
而已
- 联想
-
剩下的只有
Collectors.averagingDouble
了,那就直接进去看源码-
return new CollectorImpl<>( () -> new double[4], (a, t) -> { sumWithCompensation(a, mapper.applyAsDouble(t)); a[2]++; a[3]+= mapper.applyAsDouble(t);}, (a, b) -> { sumWithCompensation(a, b[0]); sumWithCompensation(a, b[1]); a[2] += b[2]; a[3] += b[3]; return a; }, a -> (a[2] == 0) ? 0.0d : (computeFinalSum(a) / a[2]), CH_NOID);
-
可以看到两个
mapper.applyAsDouble(t)
,其实这里就是调用我们的方法体,本质上都是对a
进行赋值操作sumWithCompensation(a, mapper.applyAsDouble(t))
操作的是a[0] a[1]
,后面操作的是a[2], a[3]
- 暂时也是挺迷惑的,为什么不在一个方法中对
a
操作完…… - 如果有答案也希望指点一二
-