Lassen Sie mich Ihr Beispiel zur Diskussion ein wenig neu formatieren:
long runCount = 0L;
myStream.stream()
.filter(...)
.forEach(item -> {
foo();
bar();
runCount++;
});
System.out.println("The lambda ran " + runCount + " times");
Wenn Sie einen Zähler wirklich aus einem Lambda heraus inkrementieren müssen, besteht die typische Methode darin, den Zähler zu einem AtomicInteger
oder zu machen AtomicLong
und dann eine der Inkrementierungsmethoden darauf aufzurufen.
Sie könnten ein einzelnes Element int
oder long
Array verwenden, dies hätte jedoch Race-Bedingungen, wenn der Stream parallel ausgeführt wird.
Beachten Sie jedoch, dass der Stream endet forEach
, was bedeutet, dass es keinen Rückgabewert gibt. Sie können das forEach
in a ändern peek
, das die Elemente durchläuft, und sie dann zählen:
long runCount = myStream.stream()
.filter(...)
.peek(item -> {
foo();
bar();
})
.count();
System.out.println("The lambda ran " + runCount + " times");
Das ist etwas besser, aber immer noch etwas seltsam. Der Grund ist, dass forEach
und peek
können ihre Arbeit nur über Nebenwirkungen erledigen. Der aufkommende Funktionsstil von Java 8 besteht darin, Nebenwirkungen zu vermeiden. Wir haben ein wenig davon getan, indem wir das Inkrement des Zählers in eine count
Operation im Stream extrahiert haben . Andere typische Nebenwirkungen sind das Hinzufügen von Elementen zu Sammlungen. In der Regel können diese durch Verwendung von Kollektoren ersetzt werden. Aber ohne zu wissen, welche Arbeit Sie tatsächlich versuchen, kann ich nichts Spezifischeres vorschlagen.