Permettetemi di riformattare il vostro esempio un po 'per il bene della discussione:
long runCount = 0L;
myStream.stream()
.filter(...)
.forEach(item -> {
foo();
bar();
runCount++; // doesn't work
});
System.out.println("The lambda ran " + runCount + " times");
Se davvero bisogno di incrementare un contatore all'interno di una lambda, il tipico modo per farlo è quello di rendere il contatore un AtomicInteger
o AtomicLong
e quindi chiamare uno dei metodi di incremento su di esso.
È possibile utilizzare un array a elemento singolo int
o long
, ma questo avrebbe condizioni di competizione se il flusso viene eseguito in parallelo.
Ma si noti che il flusso termina in forEach
, il che significa che non vi è alcun valore di ritorno. Si potrebbe cambiare il forEach
ad un peek
, che passa attraverso gli oggetti, e poi li contate:
long runCount = myStream.stream()
.filter(...)
.peek(item -> {
foo();
bar();
})
.count();
System.out.println("The lambda ran " + runCount + " times");
Questo è un po 'meglio, ma ancora un po' strano. Il motivo è che forEach
e peek
possono fare il loro lavoro solo tramite effetti collaterali. Lo stile funzionale emergente di Java 8 è quello di evitare effetti collaterali. Abbiamo fatto un po 'di ciò estraendo l'incremento del contatore in un'operazione count
sullo stream. Altri effetti collaterali tipici sono l'aggiunta di elementi alle raccolte. Di solito questi possono essere sostituiti tramite l'uso di collezionisti. Ma senza sapere quale lavoro effettivo stai cercando di fare, non posso suggerire nulla di più specifico.
fonte
2015-03-01 09:02:42
Ciao, questa è una domanda duplicata: http://stackoverflow.com/questions/23157842/cast-regular-int-to-final-java – Sliver2009
@ Sliver2009 No non lo è. –
@Florian Devi usare 'AtomicInteger' qui. –