为了账号安全,请及时绑定邮箱和手机立即绑定

一次性收集 Java Stream 的平均值

一次性收集 Java Stream 的平均值

PIPIONE 2023-07-13 15:53:53
我正在尝试找到如何收集一个衬里中的对象列表中每个字段的平均值。这是我正在尝试执行的操作:public class Value {  int a;  int b;  int c;  // rest of the class}现在假设我有List<Value> values = getMillionValues();我知道要获得一个字段的平均值,我可以执行以下操作:int averageOfA = values.stream().mapToInt(Value::getA).average()我需要做什么才能获得每个变量上面没有重复行的所有值的平均值?也许还有其他一些库,例如 Guava,可以帮助执行此类操作?
查看完整描述

1 回答

?
心有法竹

TA贡献1866条经验 获得超5个赞

说真的,使用 for 循环。


int count = 0, sumA = 0, sumB = 0, sumC = 0;

for (Value v : values) {

    sumA += v.getA();

    sumB += v.getB();

    sumC += v.getC();

    count++;

}

double avgA = ((double) sumA) / count;

double avgB = ((double) sumB) / count;

double avgC = ((double) sumC) / count;

说真的,使用上面的代码。


话虽如此,您应该使用上面的代码,但您可以使用流来完成。

您需要一些值持有者(平均值是 a double,因此您的Value类无法存储平均值):


class AveragesResult {

    public final double a, b, c;

    public AveragesResult(double a, double b, double c) {

        this.a = a;

        this.b = b;

        this.c = c;

    }

}

class AveragesIntermediate {

    public final double a, b;

    public AverageIntermediate(double a, double b) {

        this.a = a;

        this.b = b;

    }

}

现在我们已经有了样板文件(为了更好地衡量,您应该实现hashCode、equalsand toString,并添加一些 getter),我们终于可以以简短而紧凑的方式编写流:


values.stream().collect(teeing(

   teeing(averagingInt(Value::getA), averagingInt(Value::getB), AveragesIntermediate::new),

          averagingInt(Value::getC),

          (ir, avgC) -> new AveragesResult(ir.a, ir.b, avgC));

那不是很难吗?确保您已静态导入所有 Collector 函数(所有这些函数看起来都很难看Collectors.)并且您使用的Collectors.teeing是 Java 12(Java 12 中的新增功能)。


不要使用它,使用一个好的旧for循环。


查看完整回答
反对 回复 2023-07-13
  • 1 回答
  • 0 关注
  • 120 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信