【问题标题】:Why lambda forces me to use single element array instead of final object?为什么 lambda 强迫我使用单元素数组而不是最终对象?
【发布时间】:2015-05-11 18:20:56
【问题描述】:

我有以下课程:

public class Item{
   private String name;
   //setter getter
}

和项目的集合。我想获取集合中最后一个项目的名称。为此,我只需遍历所有集合并最后使用。问题是我不知道为什么它强迫我使用一个元素字符串数组。

为什么一定要使用:

String[] lastName = {""};
items.forEach(item -> lastName[0] = item.getName());
System.out.println(lastname[0]);

代替:

final String lastName;
items.forEach(item -> lastName = item.getName());
System.out.println(lastname);

【问题讨论】:

标签: java lambda java-8


【解决方案1】:

您不能将lastName 设为String,因为在lambda(或匿名内部类)中使用的局部变量必须(有效地)final (see here),即您不能覆盖它在.forEach 循环中每次执行 lambda 时。使用数组(或其他包装对象)时,您不会为该变量分配新值,而只是更改它的某些方面,因此它可以是最终的。

或者,您可以使用reduce 跳到最后一项:

String lastName = items.stream().reduce((a, b) -> b).get().getName();

或者,如 cmets 中所述,skip 第一个 n-1 个元素,然后取第一个:

String last = items.stream().skip(items.size() - 1).findFirst().get().getName();

【讨论】:

  • 这个可能效率更高,因为您不需要处理流的所有元素:String lastName = collec.stream().skip(collec.size()-1).findFirst().get().getName()
【解决方案2】:

final 实际上意味着您必须分配一次(并且只有一次,由编译时分析保证)。例如下面的代码是无效的:

final String lastName;
List<Item> items = new ArrayList<Item>();
items.add(new Item("only one element"));
for (Item item:items) lastName = item.getName();

在您的第二个 lambda 表达式中,消费者分配给 lastName,它已被声明为 final

final String lastName;
items.forEach(item -> lastName = item.getName());

由于 lambda 表达式中引用的变量必须是 effectively final(即可以将 final 关键字添加到其定义中),因此删除 lastName 声明中的 final 关键字没有帮助:这里lastName 实际上是最终的,消费者分配给一个有效的最终变量。

String lastName; 
items.forEach(item -> lastName = item.getName());

另一方面,在您的第一个表达式中,实际上是最终的变量是lastName,它是一个数组。然后你可以这样做:

  String[] lastName = {""};
  items.forEach(item -> lastName[0] = item.getName());

因为这里你没有赋值给 实际上是最终的 变量,而只是修改它的元素(请记住,常量是引用,而不是它的值),因为在下面的例子:

  final String[] lastName = new String[1];
  lastName[0]="foo";

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-15
    • 2014-06-13
    • 2012-05-02
    • 2020-08-10
    • 1970-01-01
    • 2012-09-04
    • 2017-10-15
    • 2011-10-06
    相关资源
    最近更新 更多