如何用Java中的forEach和lambda表达式求和?

时间:2018-10-13 16:34:11

标签: java lambda java-8

以下代码段无法编译。如下所示,如何使用sum查找forEach

private int Sum(ArrayList<Integer> inputs) {
    int sum = 0;

    inputs.stream().forEach(x -> sum += x);

    return sum;
}

2 个答案:

答案 0 :(得分:5)

这应该可以解决问题:

private int Sum(ArrayList<Integer> inputs) {

  return inputs.stream().mapToInt(Integer::intValue).sum();

}

编辑:

使用for-each的问题在于它是一个终端操作,这意味着它不会产生另一个中间流供我们处理。更好的方法是使用mapToInt,它会产生一个IntStream,我们可以在上面轻松地找到总和。

答案 1 :(得分:2)

这个答案只是为了提供更多有关代码为什么不起作用的背景信息,从而使您可以在将来发生问题时对问题进行解读。

您似乎是.NET用户,因此完全可以理解您所编写的代码可以正常工作。在.NET中,等效项为:

private int Sum(List<int> inputs) {
        int sum = 0;
        inputs.ForEach(x => sum += x);
        return sum;
}

但是,在Java中,lambda表达式中使用的变量必须为finaleffectively final,因此,inputs.stream().forEach(x -> sum += x);语句将无法编译。

尽管如此,仅仅因为人们期望上述代码可以在C#中工作并不一定意味着它应该在Java中工作,因为存在不同的规则。

有些解决方案可以使用forEach方法来找到一组数字的总和,但这不是惯用方法,因此除非有必要,否则应避免使用。

惯用的方法就像@Nicholas K所示。

另一方面:

  • 即使在.NET中,惯用方法也是return inputs.Sum(); 而不是使用ForEach扩展方法对给定列表的元素求和。
  • 每当您似乎在Java中使用inputs.stream().forEach(...);时,都应该改为inputs.forEach(...),因为所有列表都有forEach方法。
  • Java中的方法名称应为camelCase,而不是C#中的PascalCasing。