A lambda expression is said to be capturing if it either access instance variables of it's enclosing class or local variables (final or effectively final) from it's enclosing scope.
A non-capturing lambda doesn't use any variables from outside.
Non-capturing lambdas generally are considered more efficient than the capturing ones as they are evaluated only once.
Let's do some quick tests on different scenarios and see which one performs better.
Lambda capturing local final variables:
final BigDecimal bd = new BigDecimal(1);
Function<BigDecimal, BigDecimal> func = (a) -> bd.multiply(a);
for (int j = 0; j < 999999999; j++) {
func.apply(new BigDecimal(j));
}
Average time taken: 1725 ms
Lambda capturing local effectively final variables:
BigDecimal bd = new BigDecimal(1);
Function<BigDecimal, BigDecimal> func = (a) -> bd.multiply(a);
for (int j = 0; j < 999999999; j++) {
func.apply(new BigDecimal(j));
}
Average time taken: 1688 ms
Lambda instance variable capturing
public class LambdaInstanceCapturing implements Runnable {
private BigDecimal bd = new BigDecimal(1);
@Override
public void run() {
Function<BigDecimal, BigDecimal> func = (a) -> bd.multiply(a);
for (int j = 0; j < 999999999; j++) {
func.apply(new BigDecimal(j));
}
}
}
Average time taken: 1750 ms
Non-capturing Lambda
In this example we are just multiplying the passed BigDecimal variable with constant BigDecimal.TEN . It's still not accessing anything from outside as static final constants are inlined by the compiler .
Function<BigDecimal, BigDecimal> func = (a) -> a.multiply(BigDecimal.TEN);
for (int j = 0; j < 999999999; j++) {
func.apply(new BigDecimal(j));
}
Average time taken: 1651 ms
Conclusion:
Non-capturing Lambda is performing little better than others. But I won't suggest to make decisions based on that as things are changing with each minor release of Java 8. It's generally good to know all aspects of lambdas though.
Example ProjectDependencies and Technologies Used:
|