Pozwól sformatować Twój przykład trochę dla dobra dyskusji:
long runCount = 0L;
myStream.stream()
.filter(...)
.forEach(item -> {
foo();
bar();
runCount++; // doesn't work
});
System.out.println("The lambda ran " + runCount + " times");
Jeśli naprawdę trzeba zwiększyć licznik od wewnątrz lambda, typowy sposób, aby to zrobić jest, aby licznik AtomicInteger
lub AtomicLong
, a następnie wywołaj jedną z metod inkrementacji na nim.
Można użyć jednoczęściowej macierzy int
lub long
, ale będzie to miało warunki wyścigu, jeśli strumień jest uruchamiany równolegle.
Należy jednak zauważyć, że strumień kończy się forEach
, co oznacza, że nie ma zwracanej wartości. Można zmienić forEach
do peek
, który przechodzi poprzez elementy, a następnie policzyć:
long runCount = myStream.stream()
.filter(...)
.peek(item -> {
foo();
bar();
})
.count();
System.out.println("The lambda ran " + runCount + " times");
Jest to nieco lepiej, ale nadal nieco dziwne. Powodem jest to, że forEach
i peek
mogą wykonywać swoją pracę tylko poprzez efekty uboczne. Pojawiający się styl funkcjonalny Java 8 ma na celu uniknięcie efektów ubocznych. Zrobiliśmy trochę tego poprzez wyodrębnienie przyrostu licznika do operacji count
w strumieniu. Inne typowe efekty uboczne to dodawanie elementów do kolekcji. Zwykle można je wymienić za pomocą kolektorów. Ale nie wiedząc, jaką rzeczywistą pracę próbujesz wykonać, nie mogę sugerować niczego bardziej konkretnego.
Witaj, to jest duplikat pytania: http://stackoverflow.com/questions/23157842/cast-regular-int-to-final-java – Sliver2009
@ Sliver2009 Nie, nie jest. –
@Florian Musisz użyć 'AtomicInteger' tutaj. –