Lambda函数不会从外部范围更新数组

时间:2019-07-17 06:21:07

标签: java apache-spark lambda

如您所知,“在封闭范围内定义的局部变量必须是最终的或实际上是最终的”。所以我有以下代码

List<Airline> filteredAirlines = new ArrayList<>();
JavaRDD<Company> flightCompanyJavaRDD = rdd.map(f -> {
      ......
      results = foo(f);
      filteredAirlines.addAll(results.getFilteredAirlines());
      System.out.println(results.getFilteredAirlines().size());
      Company convertedCompanyResult = convert(results);
      return convertedCompanyResult;
});
......
System.out.println(filteredArilines.size());

第1行已打印1,第2行已打印0。列表filteredArilines似乎没有填写。有什么想法吗?以及如何获取外部可用的lambda表达式中的值?谢谢。

3 个答案:

答案 0 :(得分:0)

我不知道rdd是什么,rdd.map()是什么,但是您将lambda表达式传递给它的事实并不意味着它立即(或完全)执行。

因此,当您在摘要的最后一行中打印filteredArilines.size()时,lambda表达式可能尚未执行,因此List仍为空。

答案 1 :(得分:0)

您可以像这样将结果直接映射到列表:

List<Airline> filteredAirlines = rdd.map(f -> {
      ......
      results = foo();
      System.out.println(results.getFilteredAirlines().size());
      return results.getFilteredAirlines();
}).collect(Collectors.toList());

答案 2 :(得分:0)

  1. 您的lambda称为 closure ,因为它从外部作用域(这里是您的数组)捕获了某些东西。
  2. 完全不建议使用闭包捕获要修改的对象。这是因为它可能仅在本地模式下工作:实际上,在序列化/反序列化后,在集群模式中,每个捕获的对象将具有一个独立于每个JVM的自身版本。我指出了Spark的有关Understanding closures
  3. 的文档
  4. 最干净的方法可能是使用Accumulators