如何使用 Java 8 lambda 按顺序计算多个数字的平均值 [英] How to compute average of multiple numbers in sequence using Java 8 lambda

查看:30
本文介绍了如何使用 Java 8 lambda 按顺序计算多个数字的平均值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我有集合 Point ,如何在单次迭代中使用 Java 8 流计算 x,y 的平均值.

If I have collections Point , how do I compute average of x,y using Java 8 stream on a single iteration.

以下示例创建两个流 &在输入集合上迭代两次以计算 x & 的平均值是的.他们是否有任何方法可以使用 java 8 lambda 在单次迭代中计算平均 x,y:

Following example creates two stream & iterates twice on the input collection to compute the average of x & y. Is their any way to computer average x,y on single iteration using 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λ,最近.

If you don't mind using an additional library, we've added support for tuple collectors to jOOλ, recently.

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 实例到单个 Collector 中,将单个值收集到 元组.

In the above code, Tuple.collectors() combines several java.util.stream.Collector instances into a single Collector that collects individual values into a Tuple.

这比任何其他解决方案都更加简洁和可重复使用.你要付出的代价是它目前在包装类型上运行,而不是原始的 double.我想我们必须等到 Java 10 和原始类型的项目 valhalla专攻泛型.

This is much more concise and reusable than any other solution. The price you'll pay is that this currently operates on wrapper types, instead of primitive double. I guess we'll have to wait until Java 10 and project valhalla for primitive type specialisation in generics.

如果您想自己滚动,而不是创建依赖项,相关方法如下所示:

In case you want to roll your own, instead of creating a dependency, the relevant method looks like this:

static <T, A1, A2, D1, D2> Collector<T, Tuple2<A1, A2>, Tuple2<D1, D2>> collectors(
    Collector<T, A1, D1> collector1
  , Collector<T, A2, 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 或类似的东西.

Where Tuple2 is just a simple wrapper for two values. You might as well use AbstractMap.SimpleImmutableEntry or something similar.

我还在an answer to another Stack Overflow question中详细介绍了这种技术.

I've also detailed this technique in an answer to another Stack Overflow question.

这篇关于如何使用 Java 8 lambda 按顺序计算多个数字的平均值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆