Java Facultatif - orElse () vs orElseGet ()

Java Facultatif - orElse () vs orElseGet ()

1. introduction

L'API deOptional a généralement deux méthodes qui peuvent prêter à confusion:orElse() andorElseGet().

Dans ce rapide didacticiel, nous allons examiner la différence entre ces deux éléments et savoir quand les utiliser.

2. Les signatures

Commençons par les bases en examinant leurs signatures:

public T orElse(T other)

public T orElseGet(Supplier other)

Clairement,orElse() met tout paramètre de typew alors queorElseGet() accepte une interface fonctionnelle de typeSupplier qui renvoie un objet de typeT.

Maintenant, en fonction de leursJavadocs:

  • orElse(): renvoie la valeur si présente, sinon retourneother

  • orElseGet(): renvoie la valeur si elle est présente, sinon invoquerother and renvoie le résultat de son appel

3. Différences

Il est facile d’être un peu dérouté par ces définitions simplifiées. Voyons donc un peu plus en détail certains scénarios d’utilisation réels.

3.1. orElse()

En supposant que noslogger soient correctement configurés, commençons par écrire un simple morceau de code:

String name = Optional.of("example")
  .orElse(getRandomName());

Notez quegetRandomName()  est une méthode qui renvoie unname  aléatoire à partir d'unList<String>ofnames:

public String getRandomName() {
    LOG.info("getRandomName() method - start");

    Random random = new Random();
    int index = random.nextInt(5);

    LOG.info("getRandomName() method - end");
    return names.get(index);
}

Lors de l'exécution de notre code, nous trouverons ci-dessous les messages imprimés dans la console:

getRandomName() method - start
getRandomName() method - end

La variablename will hold “example” était à la fin de l'exécution du code.

Avec lui, on peut facilement en déduire que lesparameter of orElse() is evaluated even when having a non-empty Optional.

3.2. orElseGet()

Maintenant, essayons d'écrire un code similaire en utilisantorElseGet():

String name = Optional.of("example")
  .orElseGet(() -> getRandomName());

Le code ci-dessus n'appellera pas la méthodegetRandomName() .

Souvenez-vous (à partir du Javadoc) que la méthode Supplier passée en argument n'est exécutée que lorsque la valeuran Optional n'est pas présente.

UtiliserorElseGet()  pour notre cas nous fera donc gagner du temps dans le calcul d'unname aléatoire.

4. Mesurer l'impact sur les performances

Maintenant, pour comprendre également les différences de performances, utilisonsJMH et voyons quelques chiffres réels:

@Benchmark
@BenchmarkMode(Mode.AverageTime)
public String orElseBenchmark() {
    return Optional.of("example").orElse(getRandomName());
}

EtorElseGet():

@Benchmark
@BenchmarkMode(Mode.AverageTime)
public String orElseGetBenchmark() {
    return Optional.of("example").orElseGet(() -> getRandomName());
}

En exécutant nos méthodes de référence, nous obtenons:

Benchmark           Mode  Cnt      Score       Error  Units
orElseBenchmark     avgt   20  60934.425 ± 15115.599  ns/op
orElseGetBenchmark  avgt   20      3.798 ±     0.030  ns/op

Comme nous pouvons le constater, l’impact sur les performances peut être considérable, même pour un scénario de cas d’utilisation aussi simple.

Les chiffres ci-dessus peuvent cependant varier légèrement,orElseGet() has clearly outperformed orElse() for our particular example.

Après tout,orElse() involves le calcul degetRandomName() method pour chaque exécution.

5. Qu'est-ce qui est important?

Outre les aspects liés à la performance, il convient également de prendre en compte les facteurs suivants:

  • Et si la méthode exécuterait une logique supplémentaire? E.g. faire des insertions ou des mises à jour de la base de données

  • Même lorsque nous affectons un objet au sparamètreorElse() :

    String name = Optional.of("example").orElse("Other")

    nous sommes toujours en train de créer“Other” object sans raison

Et c’est pourquoi il est important pour nous de prendre une décision prudente parmiorElse() andorElseGet()  en fonction de nos besoins -by default, it makes more sense to use orElseGet() every time unless the default object is already constructed and accessible directly.

6. Conclusion

Dans cet article, nous avons appris les nuances entre les méthodesOptional orElse() ableOrElseGet() . Nous avons également remarqué comment parfois de tels concepts simples peuvent avoir une signification plus profonde.

Comme toujours, le code source complet peut être trouvéover on Github.