Snippet 1:
Optional.of(s).map(str -> str).orElse("");
Snippet 2:
Optional.of(s).map(str -> str).orElse(Optional.empty());
Snippet 3:
Optional.of(s).map(str -> Optional.of(str)).orElse("hello");
Snippet 1
is compiling fine but Snippet 2
& Snippet 3
compile with type incompatibility errors. While it's good that Snippet 2
& Snippet 3
fail, I do not understand how they are evaluated. In other words, I think I am missing some basics in terms of how the lambdas themselves are chained/invoked. Would appreciate if someone could help.
We can get rid of all those null checks by utilizing the Java 8 Optional type. The method map accepts a lambda expression of type Function and automatically wraps each function result into an Optional . That enables us to pipe multiple map operations in a row.
Lambda Expressions were added in Java 8. A lambda expression is a short block of code which takes in parameters and returns a value. Lambda expressions are similar to methods, but they do not need a name and they can be implemented right in the body of a method.
One of the key reasons why Java 8 is still so popular is that it is an LTS (or Long-Term Support) version. Unfortunately, not all versions of Java are LTS versions!
Q 5 - Which of the following is correct about Java 8 lambda expression? A - Lambda expressions are used primarily to define inline implementation of a functional interface.
Snippet 1:
Optional.of(s).map(str -> str).orElse("");
Compiles because the default value provided to orElse
is the same type as the value the Optional
contains i.e. a String
.
Snippet 2:
Optional.of(s).map(str -> str).orElse(Optional.empty());
does not compile because after map
you have a Optional<String>
but then you're providing a Optional<String>
in the orElse
whereas it should be a String
.
Snippet 3:
Optional.of(s).map(str -> Optional.of(str)).orElse("hello");
does not compile because after map
you have a Optional<Optional<String>>
but you're passing a String
in the orElse
whereas it should be a Optional<String>
.
To conclude orElse
is declared as:
public T orElse(T other)
and documented as:
Returns the value if present, otherwise return other.
i.e. orElse
basically says "give me the value the optional contains if present otherwise take the default value" as well as that T
must be the same type as the value the Optional
contains.
so if you have a Optional<String
then you must supply a String
to orElse
, if you have a Optional<Integer
then you must supply a Integer
to orElse
etc...
On another note, the map
function in your first and second example snippets are superfluous and you can, therefore, omit it completely.
Whenever you see your self calling Optional#map
with the function as v -> v
it's probably not needed.
Breaking down Snippet 2:
Optional.of(s) //Optional<String>
.map(str -> str) //Optional<String>
.orElse(Optional.empty()); //String or Optional<String>?
And Snippet 3:
Optional.of(s) //Optional<String>
.map(str -> Optional.of(str)) //Optional<Optional<String>>
.orElse("hello"); //Optional<String> or String?
Now, for Snippet 3, using flatMap
can be used to get rid of the nested optionals:
Optional.of(s) //Optional<String>
.flatMap(str -> Optional.of(str)) //Optional<String>
.orElse("hello"); //String
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With