使用Java 8流计算加权平均值 [英] Calculate weighted average with Java 8 streams

查看:932
本文介绍了使用Java 8流计算加权平均值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何计算Map<Double, Integer>的加权平均值,其中Integer值是要对Double值进行平均的权重. 例如:地图具有以下元素:

How do I go about calculating weighted mean of a Map<Double, Integer> where the Integer value is the weight for the Double value to be averaged. eg: Map has following elements:

  1. (0.7,100)//值为0.7权重为100
  2. (0.5,200)
  3. (0.3,300)
  4. (0.0,400)

我希望使用Java 8流应用以下公式,但是不确定如何同时计算分子和分母并保存.在这里如何使用归约?

I am looking to apply the following formula using Java 8 streams, but unsure how to calculate the numerator and denominator together and preserve it at the same time. How to use reduction here?

推荐答案

您可以为此任务创建自己的收集器:

You can create your own collector for this task:

static <T> Collector<T,?,Double> averagingWeighted(ToDoubleFunction<T> valueFunction, ToIntFunction<T> weightFunction) {
    class Box {
        double num = 0;
        long denom = 0;
    }
    return Collector.of(
             Box::new,
             (b, e) -> { 
                 b.num += valueFunction.applyAsDouble(e) * weightFunction.applyAsInt(e); 
                 b.denom += weightFunction.applyAsInt(e);
             },
             (b1, b2) -> { b1.num += b2.num; b1.denom += b2.denom; return b1; },
             b -> b.num / b.denom
           );
}

此自定义收集器采用两个函数作为参数:一个是返回用于给定流元素的值的函数(如

This custom collector takes two functions as parameter: one is a function returning the value to use for a given stream element (as a ToDoubleFunction), and the other returns the weight (as a ToIntFunction). It uses a helper local class storing the numerator and denominator during the collecting process. Each time an entry is accepted, the numerator is increased with the result of multiplying the value with its weight, and the denominator is increased with the weight. The finisher then returns the division of the two as a Double.

示例用法为:

Map<Double,Integer> map = new HashMap<>();
map.put(0.7, 100);
map.put(0.5, 200);

double weightedAverage =
  map.entrySet().stream().collect(averagingWeighted(Map.Entry::getKey, Map.Entry::getValue));

这篇关于使用Java 8流计算加权平均值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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