En java8, ¿cómo establecer el valor global en el bloque lambdas foreach?

public void test(){ String x; List list=Arrays.asList("a","b","c","d"); list.forEach(n->{ if(n.equals("d")) x="match the value"; }); } 

1. Al igual que el código anterior, quiero establecer el valor de una variable al lado del bloque foreach, ¿puede funcionar?

2. ¿Y por qué?

3. ¿Y el iterador foreach está en orden o desorden?

4.Creo que el bloque de focos de lamdas es genial y simple para el iterador, pero esto es realmente algo complicado de hacer en lugar del mismo trabajo en java 7 o antes.

Podrías, por supuesto, “hacer mutable el valor externo” a través de un truco:

 public void test() { String[] x = new String[1]; List list = Arrays.asList("a", "b", "c", "d"); list.forEach(n -> { if (n.equals("d")) x[0] = "match the value"; }); } 

Prepárate para una paliza por el purista funcional en el equipo, sin embargo. Mucho mejor, sin embargo, es utilizar un enfoque más funcional ( similar al enfoque de Sleiman ):

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

Además de los ejemplos idiomáticos ya proporcionados, otro truco sería usar AtomicReference, pero solo lo recomendaría si necesitas ‘forEach’ y prefieres algo más legible que la variante true-functional:

 public void test(){ AtomicReference x = new AtomicReference<>(); List list= Arrays.asList("a", "b", "c", "d"); list.forEach(n->{ if(n.equals("d")) x.set("match the value"); }); } 
  1. No, no puedes hacerlo. (Aunque deberías haberlo intentado tú mismo)
  2. Debido a que las variables utilizadas en las clases internas anónimas y la expresión lambda tienen que ser effectively final .
  3. puede lograr el mismo más concisamente usando filter y map .

     Optional d = list.stream() .filter(c -> c.equals("d")) .findFirst() .map(c -> "match the value"); 

Como ya se explicó, no puede modificar la variable local del método externo del cuerpo lambda (ni tampoco del cuerpo de clase anónimo). Mi consejo es que no intentes usar lambdas cuando sean completamente innecesarios. Su problema se puede resolver de esta manera:

 public void test(){ String x; List list = Arrays.asList("a","b","c","d"); if(list.contains("d")) x = "match the value"; } 

En general, los lambdas son amigos de la progtwigción funcional, donde rara vez se tienen variables mutables (cada variable se asigna solo una vez). Si usas lambdas, pero sigues pensando en estilo imperativo, siempre tendrás esos problemas.