[JAVA] Qui est plus rapide, référence de méthode ou expression lambda

introduction

Je vois souvent du code comme celui-ci:

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

Code qui crée une liste avec tous les éléments de la liste nommés «employés» traduits en noms. C'est un code normal, mais comme le type lambda est comme une classe interne, n'y a-t-il pas une surcharge? Si vous appelez juste un tel getter

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

N'est-ce pas plus rapide?

J'ai pensé, je l'ai mesuré pour m'en assurer. (Bien qu'il soit un peu vieux, il a été mesuré avec Oracle JDK 1.8u131.)

Référence de méthode ou expression lambda

référence

En utilisant JMH, j'ai mesuré le nombre d'exécutions (débit) de chaque code par seconde.

public class PerformanceMethods {
    /**Générer 10000 éléments*/
    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());
    }
}

Le résultat est ···

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

Plus le score est élevé, plus la vitesse de traitement est rapide, mais le résultat est presque le même. Si vous l'exécutez à plusieurs reprises, peu importe celui que vous utilisez.

En passant, à titre de référence, je publierai un document décrivant le mécanisme d'exécution des expressions lambda. https://www.slideshare.net/miyakawataku/lambda-meets-invokedynamic

Normalement, lorsque vous créez une classe interne, un fichier de classe est généré au moment de la compilation (classe avec "$"), mais les expressions lambda sont initialisées au moment de l'exécution, il semble donc démarrer plus rapidement. Au contraire, seul le premier moment de l'exécution de l'expression lambda sera retardé du montant de l'initialisation.

Je ne pense pas que cela me dérange, mais personnellement, j'aimerais utiliser une référence de méthode propre.

Type Lambda une ou deux fois

Lorsque j'ai examiné le code créé par d'autres, j'ai vu ce code.

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

Pour la première fois, j'ai vu comment utiliser map deux fois pour convertir lors de la création d'une liste de valeurs pour une entité imbriquée. ..

Bien sûr, j'ai écrit que "je veux personnellement utiliser une référence de méthode propre", mais il semble que map deux fois est inefficace ...?

Donc, j'ai mesuré les performances lors de l'écriture de map une fois avec une expression lambda et lors de l'écriture de map deux fois avec la référence de méthode.

référence

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());
    }
}

Le résultat est ···

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

Je suis curieux que la plage d'erreur (variation du temps de traitement) soit plus grande pour l'expression lambda (mapOnce), mais j'ai trouvé qu'une fois map est encore plus rapide.

map Il est plus facile à comprendre si vous écrivez une fois l'expression lambda. ..

Conclusion

--Il n'y a pratiquement aucune différence de vitesse entre la référence de méthode et l'expression lambda. Cependant, puisque l'expression lambda est initialisée au moment de l'exécution, il y a une petite surcharge seulement au début.

Recommended Posts

Qui est plus rapide, référence de méthode ou expression lambda
Quel est le plus rapide, Array # sample ou Random # rand?
Qu'est-ce qu'une expression lambda?
Java: dont le problème est plus rapide, en flux ou en boucle
Qu'est-ce qu'une expression lambda (Java)
Quel est le plus rapide, taille ou 0, comme argument de List # toArray?
Référence de la méthode Java8
[Java] Expression Lambda
référence de la méthode java8
Expression lambda Java
Quel est le meilleur, Kotlin ou futur Java?
Repenser les modèles d'expression et de conception de flux Java8 - Modèle de méthode