In java8, come impostare il valore globale nel blocco foreach di lambda?

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.Come il codice sopra, voglio impostare il valore di una variabile accanto al blocco foreach, può funzionare?

2. E perché?

3. E l’iteratore predefinito è in ordine o disordine?

4.Penso che il blocco di lamda foreach sia semplice e freddo per l’iteratore, ma questa è una cosa molto complicata da fare piuttosto che lo stesso lavoro in java 7 o prima.

Potresti, naturalmente, “rendere il valore esterno mutabile” tramite un trucco:

 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"; }); } 

Preparati per un pestaggio dal purista funzionale della squadra, però. Molto più bello, tuttavia, è usare un approccio più funzionale ( simile all’approccio di 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); } 

Oltre agli esempi idiomatici già forniti, un altro trucco potrebbe essere l’utilizzo di AtomicReference, ma lo raccomanderei solo se hai bisogno di “perOgni” e preferisci qualcosa di più leggibile rispetto alla variante vero-funzionale:

 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, non puoi farlo. (Anche se avresti dovuto provarlo tu stesso)
  2. Perché le variabili usate all’interno di classi interne anonime e espressioni lambda devono essere effectively final .
  3. puoi ottenere lo stesso risultato in modo più conciso usando filter e map .

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

Come già spiegato, non è ansible modificare la variabile locale del metodo esterno dal corpo lambda (così come dal corpo della class anonima). Il mio consiglio è di non provare ad usare lambda quando sono completamente inutili. Il tuo problema può essere risolto in questo modo:

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

In generale i lambda sono amici della programmazione funzionale in cui raramente si hanno variabili mutabili (ogni variabile viene assegnata una sola volta). Se usi lambda, ma continui a pensare in modo imperativo avrai sempre questi problemi.