如果我有集合点,我如何使用
Java 8流在单次迭代中计算x,y的平均值.
以下示例创建两个流&在输入集合上迭代两次,以计算x&年.是他们任何方式计算机平均x,y在单次迭代使用java 8 lambda
:
List<Point2D.Float> points = Arrays.asList(new Point2D.Float(10.0f,11.0f),new Point2D.Float(1.0f,2.9f)); // java 8,iterates twice double xAvg = points.stream().mapTodouble( p -> p.x).average().getAsDouble(); double yAvg = points.stream().mapTodouble( p -> p.y).average().getAsDouble();
解决方法
如果您不介意使用额外的图书馆,我们最近已经将元组收藏家的支持添加到了
jOOλ.
Tuple2<Double,Double> avg = points.stream().collect(
Tuple.collectors(
Collectors.averagingDouble(p -> p.x),Collectors.averagingDouble(p -> p.y)
)
);
在上面的代码中,Tuple.collectors()将几个java.util.stream.Collector实例组合成一个收集器,将各个值收集到一个元组中.
这比任何其他解决方案更简洁和可重用.你要付出的代价是这个目前的操作是包装类型,而不是原始的double.我想我们必须等到Java 10 and project valhalla for primitive type specialisation in generics.
如果您想自己滚动,而不是创建依赖关系,相关方法如下所示:
static <T,A1,A2,D1,D2> Collector<T,Tuple2<A1,A2>,Tuple2<D1,D2>> collectors(
Collector<T,D1> collector1,Collector<T,D2> collector2
) {
return Collector.of(
() -> tuple(
collector1.supplier().get(),collector2.supplier().get()
),(a,t) -> {
collector1.accumulator().accept(a.v1,t);
collector2.accumulator().accept(a.v2,t);
},(a1,a2) -> tuple(
collector1.combiner().apply(a1.v1,a2.v1),collector2.combiner().apply(a1.v2,a2.v2)
),a -> tuple(
collector1.finisher().apply(a.v1),collector2.finisher().apply(a.v2)
)
);
}
其中Tuple2只是两个值的简单包装.你也可以使用AbstractMap.SimpleImmutableEntry或类似的东西.
我也在an answer to another Stack Overflow question详细介绍了这种技术.