Which is faster, method reference or lambda expression

Introduction

I often see code like this:

employees.stream().map(e -> e.getName()).collect(Collectors.toList());

Code that creates a list with all the elements of the list named ʻemployees` translated into names. It's a normal code, but since the lambda expression is like an inner class, isn't there some overhead? If you just call such a getter,

employees.stream().map(Employee::getName).collect(Collectors.toList());

Isn't it faster?

I thought, I measured it to make sure. (Although it is a little old, it was measured with Oracle JDK 1.8u131.)

Method reference or lambda expression

benchmark

Using JMH, I measured the number of executions (throughput) of each code per second.

public class PerformanceMethods {
    /**Generate 10000 elements*/
    private static final List<Employee> employees = IntStream.range(0, 10000)
            .mapToObj(i -> new Employee(i, "name" + i))
            .collect(Collectors.toList());

    @Benchmark
    public void useReference() {
        employees.stream().map(Employee::getName).collect(Collectors.toList());
    }

    @Benchmark
    public void useLambda() {
        employees.stream().map(e -> e.getName()).collect(Collectors.toList());
    }
}

Result is···

Benchmark                         Mode  Cnt     Score     Error  Units
PerformanceMethods.useLambda     thrpt    5  5842.820 ±  65.662  ops/s
PerformanceMethods.useReference  thrpt    5  5762.353 ± 343.302  ops/s

The higher the Score, the faster the processing speed, but the result is almost the same. If you run it repeatedly, it doesn't matter which one you use.

By the way, as a reference, I will post a document that describes the mechanism of lambda expression execution. https://www.slideshare.net/miyakawataku/lambda-meets-invokedynamic

Normally, when you create an inner class, a class file is generated at compile time (class with "$"), but lambda expressions are initialized at runtime, so it seems to start faster. If you take it the other way around, it means that only the first timing to execute the lambda expression will be delayed by the amount of initialization.

I don't think it bothers me, but personally I would like to use a clean method reference.

Lambda expression once or map twice

When I was reviewing code made by others, I saw this code.

employees.stream().map(Employee::getAddress).map(Address::getPostalCode).collect(Collectors.toList());

For the first time, I saw how to use map twice to convert when creating a list of values for nested entities. ..

Sure, I wrote that "I personally want to use a clean method reference", but it seems that map twice is inefficient ...?

So, I measured the performance when writing map once with one lambda expression and when writing map twice with the method reference.

benchmark

public class PerformanceMethods {
    private static final List<Employee> employees = IntStream.range(0, 10000)
            .mapToObj(i -> new Employee(i, "name" + i, new Address("code" + i)))
            .collect(Collectors.toList());

    @Benchmark
    public void mapOnce() {
        employees.stream()
                 .map(e -> e.getAddress().getCode())
                 .collect(Collectors.toList());
    }

    @Benchmark
    public void mapTwice() {
        employees.stream()
                 .map(Employee::getAddress)
                 .map(Address::getCode)
                 .collect(Collectors.toList());
    }
}

Result is···

Benchmark                     Mode  Cnt     Score      Error  Units
PerformanceMethods.mapOnce   thrpt    5  6340.454 ± 1291.055  ops/s
PerformanceMethods.mapTwice  thrpt    5  5487.546 ±  488.373  ops/s

I'm curious that the lambda expression (mapOnce) has a larger range of Error (variation in processing time), but I found that map once is still faster.

map It's easier to understand if you write the lambda expression once. ..

Conclusion

--There is almost no difference in speed between the method reference and the lambda expression. However, since the lambda expression is initialized at runtime, there is a little overhead at the beginning. --It's faster to write a map once using a lambda expression than to take a value using a method reference twice. And easy to read.

Recommended Posts

Which is faster, method reference or lambda expression
Which is faster, Array # sample or Random # rand?
What is a lambda expression?
Java: The problem of which is faster, stream or loop
What is a lambda expression (Java)
Which is faster, size or 0, as the argument of List # toArray?
Java8 method reference
[Java] Lambda expression
java8 method reference
Java lambda expression
Which is better, Kotlin or Java in the future?
Java8 Lambda expression & Stream design pattern reconsideration --Template Method pattern -