如果我有集合点,我如何使用
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详细介绍了这种技术.