封闭范围中定义的局部变量计数必须是最终的或有效地最终

时间:2018-08-04 14:16:51

标签: java

我正在尝试使用Java lambda表达式计算迭代次数,但是会引发编译时错误:

Local variable count defined in an enclosing scope must be final or effectively final

public static void main(String[] args) {

  List<String> names = new ArrayList<String>();
  names.add("Ajeet");
  names.add("Negan");
  names.add("Aditya");
  names.add("Steve");

  int count = 0;

  names.stream().forEach(s->
  {
    if(s.length()>6)
        count++;
  });
}

3 个答案:

答案 0 :(得分:5)

您不能从Lambda的外部范围访问非final变量。但是您不需要在这里,您可以根据自己的条件filter streamcount。喜欢,

long count = names.stream().filter(s -> s.length() > 6).count();

答案 1 :(得分:4)

语句count++;正在重新分配变量count

这在lambda表达式中是不允许的。在lambda中引用的局部变量必须是最终变量(或有效地是最终变量,这意味着它没有显式声明为最终变量,但是如果添加了final则不会中断)

替代方法是使用原子整数:

AtomicInteger count = new AtomicInteger();

names.stream().forEach(s -> {
    if (s.length() > 6)
        count.incrementAndGet();
});

注意 ,仅当需要修改局部变量时,才应使用原子整数。如果所有这些只是为了计算count变量,那么EliotFrish答案中的方法要好得多。

答案 2 :(得分:0)

此答案仅是为了提供更广泛的方法来克服此错误。

您可以定义自己的消费者,其计数:

NSInputStream

然后将这个新类的实例传递给使用者:

- (void)scheduleInRunLoop:(__unused NSRunLoop *)aRunLoop
              forMode:(__unused NSString *)mode
{}

- (void)removeFromRunLoop:(__unused NSRunLoop *)aRunLoop
              forMode:(__unused NSString *)mode
{}

最终让您在迭代后提取计数:

class CountingConsumer implements Consumer<String>{
    int count;

    public void accept(String s){
        if(s.length() > 6){
            count++;
        }
    }
}

但是更好的答案是使用普通的for循环:

CountingConsumer countingConsumer = new CountingConsumer();
names.forEach(countingConsumer);