Java 8 计算总和时,Lambda中使用的变量应为final或effective final?
我有一张包含地图的地图。 地图> 对于映射中的所有条目,我想计算特定键的和 例如,我的地图是这样的:Java 8 计算总和时,Lambda中使用的变量应为final或effective final?,java-8,Java 8,我有一张包含地图的地图。 地图> 对于映射中的所有条目,我想计算特定键的和 例如,我的地图是这样的: Key1 Key2 Value A Z 10.10 B Z 40.10 C Y 20.10 我想基本上计算所有key2的和,它等于B。所以在这个例子中,我想得到50.20,因为Key1-C没有key2z 我正在尝试使用Java8来实现这一点。我不知道该如何收取这笔款项 double sum = 0; myMap
Key1 Key2 Value
A Z 10.10
B Z 40.10
C Y 20.10
我想基本上计算所有key2的和,它等于B。所以在这个例子中,我想得到50.20,因为Key1-C没有key2z
我正在尝试使用Java8来实现这一点。我不知道该如何收取这笔款项
double sum = 0;
myMap.forEach((key1, key2) -> {
sum += key2.get("Z");
});
但是我得到一个错误,说lambda中的值应该是最终值 您可以使用流。这样,您也可以使用中间操作:
myMap.entrySet().stream()
.filter(entry -> entry.getValue().equals(Z))
.map(entry -> entry.getValue())
.mapToDouble(v -> v.get("Z"))
.sum()
我不确定您的数据结构,因此这可能需要一些工作,但我希望您能理解
您的方法不起作用,因为您试图在无法修改的范围内修改局部变量。看
tl;dr您不能修改lambda主体中的局部变量。匿名内部类或lambda中使用的所有外部变量都必须是(永远不会重新分配的非最终变量) 在您的解决方案中,您试图用函数式解决方案修复经典的命令式解决方案 惯用的Java-8方法是使用流API:
map.values().stream()
.map(x -> x.get("Z"))
.reduce(0, Double::sum);
或者使用专门的流
进行double
s:
map.values().stream()
.mapToDouble(x -> x.get("Z"))
.sum()
记住要正确处理边缘情况。如果没有与“Z”键相关联的值,这将爆炸。您已经得到了如何正确使用流的答案(您的示例)。但有时这是不可行的(即使在jdk源代码中,也有需要数组包装器的地方):
或者您可以使用它的线程安全性
map.values().stream().mapToDouble(x->x.get(“Z”)).sum()
预期会出现错误。如果要从lambda中访问sum
,则必须是final。您无法从lambda中获取对任何非final的引用。只需在映射之前应用筛选器,以确保“Z”键存在。
double [] sum = {0};
myMap.forEach((key1, key2) -> {
sum[0] += key2.get("Z");
});