The difference between `Optional.orElse ()` and `Optional.orElseGet ()`

I am trying to understand the difference between Optional<T>.orElse() and Optional<T>.orElseGet() .

orElse() method orElse() : "Return the value, if present, otherwise return another."

While the description of the orElseGet() method is "Return a value if it is present, otherwise call another and return the result of this call."

The orElseGet() method uses the provider functional interface, which essentially takes no parameters and returns T

In what situation would you need to use orElseGet() ? If you have the T myDefault() method T myDefault() , why don't you just do optional.orElse(myDefault()) rather than optional.orElseGet(() -> myDefault()) ?

It seems that orElseGet() postpones the execution of the lambda expression until some later time or something like that, and what is that point? (I would have thought that it would be more useful if he returned a more secure Optional<T> , which get() never throws a NoSuchElementException and isPresent() always returns true ... but obviously it isn’t, it just returns T e.g. orElse() ).

Is there any other difference I'm missing?

+180
java java-8 optional
Oct 16 '15 at 12:05
source share
7 answers

Take these two scenarios:

 Optional<Foo> opt = ... Foo x = opt.orElse( new Foo() ); Foo y = opt.orElseGet( Foo::new ); 

If opt does not contain a value, they are really equivalent. But if opt contains a value, how many Foo objects will be created?

Ps: of course, in this example, the difference is probably not measurable, but if you need to get the default value from a remote web service, for example, or from a database, it suddenly becomes very important.

+151
Oct. 16 '15 at 12:08
source share

Short answer:

  • orElse () will always call this function, whether you want it or not, regardless of the value of Optional.isPresent()
  • orElseGet () will call this function only when Optional.isPresent() == false

In real code, you can consider the second approach when the required resource is expensive .

 // Always get heavy resource getResource(resourceId).orElse(getHeavyResource()); // Get heavy resource when required. getResource(resourceId).orElseGet(() -> getHeavyResource()) 

For more information, consider the following example with this function:

 public Optional<String> findMyPhone(int phoneId) 

The difference is as below:

  X : buyNewExpensivePhone() called +β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”+β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”+ | Optional.isPresent() | true | false | +β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”+β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”+ | findMyPhone(int phoneId).orElse(buyNewExpensivePhone()) | X | X | +β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”+β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”+ | findMyPhone(int phoneId).orElseGet(() -> buyNewExpensivePhone()) | | X | +β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”+β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”+ 

If optional.isPresent() == false , there is no difference between the two methods. However, when orElse() optional.isPresent() == true , orElse() always calls the next function, whether you want it or not.

And finally, the test case used, as shown below:

Result:

 ------------- Scenario 1 - orElse() -------------------- 1.1. Optional.isPresent() == true Going to a very far store to buy a new expensive phone Used phone: MyCheapPhone 1.2. Optional.isPresent() == false Going to a very far store to buy a new expensive phone Used phone: NewExpensivePhone ------------- Scenario 2 - orElseGet() -------------------- 2.1. Optional.isPresent() == true Used phone: MyCheapPhone 2.2. Optional.isPresent() == false Going to a very far store to buy a new expensive phone Used phone: NewExpensivePhone 

The code:

 public class TestOptional { public Optional<String> findMyPhone(int phoneId) { return phoneId == 10 ? Optional.of("MyCheapPhone") : Optional.empty(); } public String buyNewExpensivePhone() { System.out.println("\tGoing to a very far store to buy a new expensive phone"); return "NewExpensivePhone"; } public static void main(String[] args) { TestOptional test = new TestOptional(); String phone; System.out.println("------------- Scenario 1 - orElse() --------------------"); System.out.println(" 1.1. Optional.isPresent() == true"); phone = test.findMyPhone(10).orElse(test.buyNewExpensivePhone()); System.out.println("\tUsed phone: " + phone + "\n"); System.out.println(" 1.2. Optional.isPresent() == false"); phone = test.findMyPhone(-1).orElse(test.buyNewExpensivePhone()); System.out.println("\tUsed phone: " + phone + "\n"); System.out.println("------------- Scenario 2 - orElseGet() --------------------"); System.out.println(" 2.1. Optional.isPresent() == true"); // Can be written as test::buyNewExpensivePhone phone = test.findMyPhone(10).orElseGet(() -> test.buyNewExpensivePhone()); System.out.println("\tUsed phone: " + phone + "\n"); System.out.println(" 2.2. Optional.isPresent() == false"); phone = test.findMyPhone(-1).orElseGet(() -> test.buyNewExpensivePhone()); System.out.println("\tUsed phone: " + phone + "\n"); } } 
+85
Dec 23 '17 at 9:41 on
source share

I reached here for the problem that Kudo was talking about.

I share my experience with others.

orElse or orElseGet , this is the question:

 static String B() { System.out.println("B()..."); return "B"; } public static void main(final String... args) { System.out.println(Optional.of("A").orElse(B())); System.out.println(Optional.of("A").orElseGet(() -> B())); } 

seal

 B()... A A 

orElse evaluates to B () regardless of the value of optional. So orElseGet lazy.

+59
Oct 21 '16 at 4:13
source share

I would say that the biggest difference between orElse and orElseGet happens when we want to evaluate something to get a new value in else .

Consider this simple example -

 // oldValue is String type field that can be NULL String value; if (oldValue != null) { value = oldValue; } else { value = apicall().value; } 

Now let's move on to the example above, using Optional with orElse ,

 // oldValue is Optional type field String value = oldValue.orElse(apicall().value); 

Now change the above example to use Optional with orElseGet ,

 // oldValue is Optional type field String value = oldValue.orElseGet(() -> apicall().value); 

When orElse is orElse , apicall().value is evaluated and passed to the method. Whereas in the case of orElseGet evaluation is performed only if oldValue empty. orElseGet allows lazy pricing.

+35
Jan 19 '17 at 19:06 on
source share

The difference is quite subtle, and if you do not pay much attention, you will use it incorrectly.

The best way to understand the difference between orElse() and orElseGet() is that orElse() will always be executed if Optional<T> is zero or not , but orElseGet() will only be executed when Optional<T> is zero .

In the dictionary, the value of orElse is : - execute the part when something is missing, but here it contradicts, see the example below:

  Optional<String> nonEmptyOptional = Optional.of("Vishwa Ratna"); String value = nonEmptyOptional.orElse(iAmStillExecuted()); public static String iAmStillExecuted(){ System.out.println("nonEmptyOptional is not NULL,still I am being executed"); return "I got executed"; } 

Conclusion: nonEmptyOptional is not NULL, but I'm still running




  Optional<String> emptyOptional = Optional.ofNullable(null); String value = emptyOptional.orElse(iAmStillExecuted()); public static String iAmStillExecuted(){ System.out.println("emptyOptional is NULL, I am being executed, it is normal as per dictionary"); return "I got executed"; } 

Output : emptyOptional VALID, I execute, this is normal according to the dictionary

For orElseGet() , the method goes according to the value of the dictionary, the orElseGet() will be executed only when optionally zero .

Benchmarks :

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

Remarks : orElseGet() clearly superior to orElse() for our specific example.

I hope this clarifies the doubts of people like me who want to get the simplest example in life :)

+3
Aug 23 '19 at 12:57 on
source share

The following example should demonstrate the difference:

 String destroyTheWorld() { // destroy the world logic return "successfully destroyed the world"; } Optional<String> opt = Optional.empty(); // we're dead opt.orElse(destroyTheWorld()); // we're safe opt.orElseGet(() -> destroyTheWorld()); 

The answer also appears in the docs.

public T orElseGet(Supplier<? extends T> other) :

Return the value if it is present, otherwise call other and return the result of this call.

Supplier will not be called if Optional gifts. while,

public T orElse(T other) :

Return the value if it is present, otherwise return another.

If other is a method that returns a string, it will be called, but this value will not be returned if Optional exists.

+2
Mar 17 '19 at 12:53 on
source share

Given the following code:

 import java.util.Optional; // one class needs to have a main() method public class Test { public String orelesMethod() { System.out.println("in the Method"); return "hello"; } public void test() { String value; value = Optional.<String>ofNullable("test").orElseGet(this::orelesMethod); System.out.println(value); value = Optional.<String>ofNullable("test").orElse(orelesMethod()); System.out.println(value); } // arguments are passed using the text field below this editor public static void main(String[] args) { Test test = new Test(); test.test(); } } 

if we get value as follows: Optional.<String>ofNullable(null) , there is no difference between orElseGet () and orElse (), but if we get value this way: Optional.<String>ofNullable("test") , orelesMethod() in orElseGet() will not be called, but in orElse() it will be called

0
Aug 20
source share



All Articles