Collectors.averagingDouble() 忘是亡心i 2021-09-22 02:34 138阅读 0赞 ## 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 ## 为什么会这样打印两遍值? ## 1. 详细对比了一下map,并打印相应的值 1. 结论: 只打印一遍,说明流式操作只进行一次流式操作,排除map以及之前操作 2. `collect`是一个收集器,收集传输过来的元素,并没有实际作用 1. 联想`Collectors.toList()`推断出没有重复的值 2. 观察源码发现,其实际上就是`container`而已 3. 剩下的只有`Collectors.averagingDouble`了,那就直接进去看源码 1. 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); 2. 可以看到两个`mapper.applyAsDouble(t)`,其实这里就是调用我们的方法体,本质上都是对`a`进行赋值操作 1. `sumWithCompensation(a, mapper.applyAsDouble(t))`操作的是`a[0] a[1]`,后面操作的是 `a[2], a[3]` 2. 暂时也是挺迷惑的,为什么不在一个方法中对`a`操作完…… 3. 如果有答案也希望指点一二
还没有评论,来说两句吧...