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");
});