在java8中,如何在lambdas foreach块中设置全局值?

Mar*_*ung 28 java foreach lambda java-8

    public void test(){
       String x;
       List<String> list=Arrays.asList("a","b","c","d");

       list.forEach(n->{
          if(n.equals("d"))
            x="match the value";
       });
    }
Run Code Online (Sandbox Code Playgroud)

1.像上面的代码一样,我想在foreach块旁边设置一个变量的值,它可以工作吗?

2.为什么?

3. foreach迭代器是有序的还是无序的?

4.我认为lamdas foreach块对于迭代器来说很酷且很简单,但这实际上是一件很复杂的事情,而不是java 7或之前的相同工作.

Luk*_*der 24

当然,你可以通过一个技巧"使外部价值变得可变":

public void test() {
    String[] x = new String[1];
    List<String> list = Arrays.asList("a", "b", "c", "d");

    list.forEach(n -> {
        if (n.equals("d"))
            x[0] = "match the value";
    });
}
Run Code Online (Sandbox Code Playgroud)

但是,准备好让团队中的功能性纯粹主义者挨打.然而,更好的是使用更实用的方法(类似于Sleiman的方法):

public void test() {
    List<String> list = Arrays.asList("a", "b", "c", "d");
    String x = list.stream()
                   .filter("d"::equals)
                   .findAny()
                   .map(v -> "match the value")
                   .orElse(null);
}
Run Code Online (Sandbox Code Playgroud)

  • @RalfKleberhoff:适合自己。 (4认同)

And*_*sov 9

除了已经提供的惯用示例之外,另一个黑客将是使用AtomicReference,但我只推荐它,如果你确实需要'forEach'并且更喜欢比真实功能变体更可读的东西:

public void test(){
    AtomicReference<String> x = new AtomicReference<>();
    List<String> list= Arrays.asList("a", "b", "c", "d");

    list.forEach(n->{
        if(n.equals("d"))
            x.set("match the value");
    });
}
Run Code Online (Sandbox Code Playgroud)

  • 仅支持“AtomicReference”,但我不会推荐它用于 foreach。相反,如果用于并行流,这种方法是有意义的。 (2认同)

Sle*_*idi 8

  1. 不,你做不到.(虽然你应该亲自试过)
  2. 因为匿名内部类和lambda表达式中使用的变量必须是effectively final.
  3. 你可以使用filter和更简洁地实现同样的目标map.

    Optional<String> d = list.stream()
                             .filter(c -> c.equals("d"))
                             .findFirst()
                             .map(c -> "match the value");
    
    Run Code Online (Sandbox Code Playgroud)


Tag*_*eev 6

正如已经解释的那样,你不能从lambda体(以及匿名类体)修改外部方法的局部变量.我的建议是,当它们完全没必要时,不要尝试使用lambdas.您的问题可以像这样解决:

public void test(){
   String x;
   List<String> list = Arrays.asList("a","b","c","d");
   if(list.contains("d"))
       x = "match the value";
}
Run Code Online (Sandbox Code Playgroud)

一般来说,lambdas是功能编程的朋友,你很少有可变变量(每个变量只分配一次).如果你使用lambdas,但继续以命令式的方式思考,你总会遇到这样的问题.

  • 作为旁注,你的代码确实与OP的代码匹配,因为`x`之后完全没用,因为可能没有分配. (3认同)