我有一张包含地图的地图。 地图> 对于地图中的所有条目,我想计算特定键的总和。
例如我的地图是这样的:
Key1 Key2 Value
A Z 10.10
B Z 40.10
C Y 20.10
我想基本上计算所有key2的总和,它等于B.所以在这种情况下我想得到50.20因为Key1 -C没有key2 Z
我正在尝试使用Java 8.我不知道如何收集总和。
double sum = 0;
myMap.forEach((key1, key2) -> {
sum += key2.get("Z");
});
但后来我得到一个错误,说lambda中的值应该是final。
答案 0 :(得分:3)
匿名内部类或Lambda中使用的所有外部变量都必须是final or effectively final(永不重新分配的非最终变量)。
在您的解决方案中,您正尝试使用功能性解决方案来修复经典命令解决方案。
惯用的Java-8方法是使用Stream API:
map.values().stream()
.map(x -> x.get("Z"))
.reduce(0, Double::sum);
或将专门的Stream
用于double
s:
map.values().stream()
.mapToDouble(x -> x.get("Z"))
.sum()
请记住正确处理边缘情况。如果没有与“Z”键相关联的值,则会爆炸。
答案 1 :(得分:1)
您可以使用Stream。这样你也可以使用中间操作:
myMap.entrySet().stream()
.filter(entry -> entry.getValue().equals(Z))
.map(entry -> entry.getValue())
.mapToDouble(v -> v.get("Z"))
.sum()
我不确定您的数据结构,所以这可能需要一些工作,但我希望您明白这一点。
https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html
您的方法不起作用,因为您尝试在无法修改的范围内修改局部变量。见http://docs.oracle.com/javase/tutorial/java/javaOO/localclasses.html
tl; dr您无法修改lambda体中的局部变量。
答案 2 :(得分:0)
你得到了如何正确地(你的例子)用流做的答案。有时候这是不可行的(即使在jdk源代码中也存在需要数组包装器的地方):
double [] sum = {0};
myMap.forEach((key1, key2) -> {
sum[0] += key2.get("Z");
});
答案 3 :(得分:0)
或者您可以使用AtomicInteger,它是threadSafe