I face the same problem often. I need to count the runs of a lambda for use outside the lambda.
E.g.:
myStream.stream().filter(...).forEa
Another way of doing this (useful if you'd like your count to only be incremented in some cases, like if an operation was successful) is something like this, using mapToInt()
and sum()
:
int count = myStream.stream()
.filter(...)
.mapToInt(item -> {
foo();
if (bar()){
return 1;
} else {
return 0;
})
.sum();
System.out.println("The lambda ran " + count + "times");
As Stuart Marks noted, this is still somewhat odd, because it's not completely avoiding side effects (depending on what foo()
and bar()
are doing).
And another way of incrementing a variable in a lambda that's accessible outside of it is to use a class variable:
public class MyClass {
private int myCount;
// Constructor, other methods here
void myMethod(){
// does something to get myStream
myCount = 0;
myStream.stream()
.filter(...)
.forEach(item->{
foo();
myCount++;
});
}
}
In this example, using a class variable for a counter in one method probably doesn't make sense, so I'd caution against it unless there's a good reason to. Keeping class variables final
if possible can be helpful in terms of thread safety, etc (see http://www.javapractices.com/topic/TopicAction.do?Id=23 for a discussion on using final
).
To get a better idea of why lambdas work the way they do, https://www.infoq.com/articles/Java-8-Lambdas-A-Peek-Under-the-Hood has a detailed look.