首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用Java 8流计算加权平均

用Java 8流计算加权平均
EN

Stack Overflow用户
提问于 2016-11-04 10:14:12
回答 4查看 13.4K关注 0票数 15

如何计算Map<Double, Integer>的加权平均值,其中整数值是要平均的双值的权重。地图有以下要素:

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

我希望使用Java 8流应用以下公式,但不确定如何同时计算分子和分母,并同时保存它们。这里怎么用减价?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2016-11-04 10:51:54

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

代码语言:javascript
复制
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
           );
}

这个自定义收集器使用两个函数作为参数:一个函数返回用于给定流元素的值(作为ToDoubleFunction),另一个函数返回权重(作为ToIntFunction)。它使用一个助手本地类,在收集过程中存储分子和分母。每次接受一个条目时,分子都会随着值与其权重的乘积而增加,分母也会随着权重的增加而增加。然后,finisher将两者的除法作为Double返回。

示例用法如下:

代码语言:javascript
复制
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));
票数 21
EN

Stack Overflow用户

发布于 2017-06-27 18:33:58

您可以使用此过程计算地图的加权平均值。注意,映射条目的键应该包含值,映射条目的值应该包含权重。

代码语言:javascript
复制
     /**
     * Calculates the weighted average of a map.
     *
     * @throws ArithmeticException If divide by zero happens
     * @param map A map of values and weights
     * @return The weighted average of the map
     */
    static Double calculateWeightedAverage(Map<Double, Integer> map) throws ArithmeticException {
        double num = 0;
        double denom = 0;
        for (Map.Entry<Double, Integer> entry : map.entrySet()) {
            num += entry.getKey() * entry.getValue();
            denom += entry.getValue();
        }

        return num / denom;
    }

您可以通过它的单元测试来查看usecase。

代码语言:javascript
复制
     /**
     * Tests our method to calculate the weighted average.
     */
    @Test
    public void testAveragingWeighted() {
        Map<Double, Integer> map = new HashMap<>();
        map.put(0.7, 100);
        map.put(0.5, 200);
        Double weightedAverage = calculateWeightedAverage(map);
        Assert.assertTrue(weightedAverage.equals(0.5666666666666667));
    }

单元测试需要这些导入:

代码语言:javascript
复制
import org.junit.Assert;
import org.junit.Test;

代码需要这些导入:

代码语言:javascript
复制
import java.util.HashMap;
import java.util.Map;

希望能帮上忙。

票数 3
EN

Stack Overflow用户

发布于 2020-11-19 14:13:40

代码语言:javascript
复制
public static double weightedAvg(Collection<Map.Entry<? extends Number, ? extends Number> data) {
    var sumWeights = data.stream()
        .map(Map.Entry::getKey)
        .mapToDouble(Number::doubleValue)
        .sum();
    var sumData = data.stream()
        .mapToDouble(e -> e.getKey().doubleValue() * e.getValue().doubleValue())
        .sum();
    return sumData / sumWeights;
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40420069

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档