如何計算Map<Double, Integer>
的加權平均值,其中Integer值是Double值的平均權重。 例如:地圖具有以下要素:使用Java 8流計算加權平均值
- (0.7,100)//值爲0.7和重量爲100
- (0.5,200)
- (0.3,300)
- (0.0, 400)
我正在尋找使用Java 8流應用以下公式,但不確定如何計算分子和分母在一起並同時保留它。如何在這裏使用減少?
如何計算Map<Double, Integer>
的加權平均值,其中Integer值是Double值的平均權重。 例如:地圖具有以下要素:使用Java 8流計算加權平均值
我正在尋找使用Java 8流應用以下公式,但不確定如何計算分子和分母在一起並同時保留它。如何在這裏使用減少?
您可以創建自己的收集完成這個任務:
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
)。它使用一個輔助本地類來存儲收集過程中的分子和分母。每次輸入被接受時,分子都會隨着它的權重乘以結果而增加,並且分母隨着權重而增加。終結者然後將兩者的劃分返回爲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));
謝謝你的這個精彩的解釋。我會閱讀更多關於定製收藏家的信息。 –
可以使用此過程來計算的映射的加權平均。請注意,地圖條目的關鍵字應該包含該值,而地圖條目的值應該包含重量。
/**
* 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;
}
你可以看看它的單元測試看看一個用例。
/**
* 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));
}
您需要這些進口的單元測試:
import org.junit.Assert;
import org.junit.Test;
您需要這些進口代碼:
import java.util.HashMap;
import java.util.Map;
我希望它能幫助。
您是否檢查了['Collectors.averagingDouble'](https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html#averagingDouble-java.util.function .ToDoubleFunction-)方法? – Aaron