Java Opzionale - orElse () vs orElseGet ()

1. Introduzione

L'API di Optional ha in genere due metodi che possono causare confusione: orElse () e orElseGet () .

In questo rapido tutorial, esamineremo la differenza tra questi due ed esploreremo quando utilizzarli.

2. Firme

Iniziamo prima con le basi guardando le loro firme:

public T orElse(T other) public T orElseGet(Supplier other)

Chiaramente, orelse () prende qualsiasi parametro di tipo T che orElseGet () accetta un'interfaccia funzionale di tipo fornitore che restituisce un oggetto di tipo T .

Ora, in base ai loro Javadoc:

  • orElse () : restituisce il valore se presente, altrimenti restituisce altro
  • orElseGet (): restituisce il valore se presente, altrimenti invoca altro e restituisce il risultato della sua invocazione

3. Differenze

È facile essere un po 'confusi da queste definizioni semplificate, quindi scaviamo un po' più a fondo e guardiamo alcuni scenari di utilizzo reali.

3.1. o altro()

Supponendo di avere il nostro logger configurato correttamente, iniziamo con la scrittura di un semplice pezzo di codice:

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

Si noti che getRandomName () è un metodo che restituisce un nome casuale da un elenco di nomi:

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

Eseguendo il nostro codice, troveremo di seguito i messaggi stampati nella console:

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

Il nome della variabile conterrà "baeldung" alla fine dell'esecuzione del codice.

Con esso, possiamo facilmente dedurre che il parametro di orElse () viene valutato anche quando si ha un Opzionale non vuoto .

3.2. orElseGet ()

Ora, proviamo a scrivere codice simile usando orElseGet () :

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

Il codice precedente non richiamerà il metodo getRandomName () .

Ricorda (dal Javadoc) che il metodo S upplier passato come argomento viene eseguito solo quando un valore opzionale non è presente.

L'uso di orElseGet () per il nostro caso, quindi, ci farà risparmiare un po 'di tempo nel calcolo di un nome casuale .

4. Misurazione dell'impatto sulle prestazioni

Ora, per capire anche le differenze di prestazioni, usiamo JMH e vediamo alcuni numeri reali:

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

E orElseGet () :

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

Durante l'esecuzione dei nostri metodi di benchmark, otteniamo:

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

Come possiamo vedere, l'impatto sulle prestazioni potrebbe essere sostanziale anche per uno scenario di caso d'uso così semplice.

I numeri sopra potrebbero variare leggermente, tuttavia, o ElseGet () ha chiaramente sovraperformato oElse () per il nostro esempio particolare.

Dopotutto, orElse () implica il calcolo del metodo getRandomName () per ogni esecuzione.

5. Cosa è importante?

Oltre agli aspetti prestazionali, altri fattori degni di considerazione riguardano:

  • E se il metodo eseguisse una logica aggiuntiva? Ad esempio facendo alcuni inserimenti o aggiornamenti di DB
  • Anche quando assegniamo un oggetto al parametro orElse () :
    String name = Optional.of("baeldung").orElse("Other")

    stiamo ancora creando un oggetto "Altro" senza motivo

Ed è per questo che è importante per noi prendere una decisione attenta tra orElse () e orElseGet () a seconda delle nostre esigenze: per impostazione predefinita, ha più senso usare orElseGet () ogni volta a meno che l'oggetto predefinito non sia già costruito e accessibile direttamente .

6. Conclusione

In questo articolo, abbiamo appreso le sfumature tra i metodi Optional orElse () e OrElseGet () . Abbiamo anche notato come a volte concetti così semplici possano avere un significato più profondo.

Come sempre, il codice sorgente completo può essere trovato su Github.