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

查看:821
本文介绍了如何使用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&的平均值。年。他们以任何方式计算机平均x,y在单次迭代中使用java 8 lambda

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

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.

我还在回答另一个Stack Overflow问题

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

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