Edit
After watching Stuart Marks' (who works for the core libraries team in the JDK group at Oracle) talk "Optional – The Mother of All Bikesheds" from Devoxx 2016, you should jump to 54:04:
Why Not Use Optional in Fields?
- More a style issue than a correctness issue
- usually there's a better way to model absence of a value
- use of Optional in fields often arises from slavish desire to eliminate nullable fields
- remember, eliminating nulls isn't a goal of Optional
- Using Optional in fields...
- creates another object for every field
- introduces a dependent load from memory on every field read
- clutters up your code
- to what benefit? ability to chain methods?
Original Post
According to IntelliJ's inspector (Preferences > Editor > Inspections > 'Optional' used as field or parameter type):
Optional was designed to provide a limited mechanism for library method return types where there needed to be a clear way to represent "no result". Using a field with type
java.util.Optionalis also problematic if the class needs to beSerializable, whichjava.util.Optionalis not.
This also applies to collections in case you have to serialize them. Furthermore, have a look at these links:
Java 8 Optional: What's the Point?
So to recap - in an attempt to get rid of NullPointerExceptions we have a new class that:
- Throws NullPointerExceptions
- Can itself be null, causing a NullPointerException
- Increases heap size
- Makes debugging more difficult
- Makes serializing objects, say as an XML or JSON for an external client, much more difficult
Why java.util.Optional is broken
The final irony is that by attempting to discourage nulls, the authors of this class have actually encouraged its use. I'm sure there are a few who will be tempted to simply return null from their functions in order to "avoid creating an unnecessary and expensive Optional reference", rather than using the correct types and combinators.
If you care about readability, you could also use @Nullable (available in Eclipse as well as in IntelliJ):
class ConnectionBox {
@Nullable
Connection connection;
// ...
}
Alternatively, you can create an optional getter:
class ConnectionBox {
Connection connection;
// ...
Optional<Connection> getConnection() {
return Optional.ofNullable(connection);
}
}
Answer from beatngu13 on Stack Overflowjava - Use of Optional in a map - Stack Overflow
java - How to make `Map::get` return either an `Optional` of the found value or `Optional.empty()` - Stack Overflow
option type - Existing way to Java map Optional<> onto object instead of to another object? - Stack Overflow
java - How does Optional.map() exactly works? - Stack Overflow
Videos
Why not simply:
Copyreturn Optional.ofNullable(myMap.get(myKey));
JavaDocs
This
CopyOptional.of(myMap.getOrDefault(myKey, null));
or really
CopyOptional.of(null);
would've failed with a NullPointerException. As the javadoc states
Throws:
NullPointerException - ifvalueis null
Optional#ofNullable exists when you don't know if the value you're passing to it is null or not:
Parameters:
value- the possibly-null value to describe
And since Map#get(Object) already returns null when there is no entry for the given key
Returns:
the value to which the specified key is mapped, ornullif this map contains no mapping for the key
you don't need to use getOrDefault with a null value for the default. You can instead directly use
CopyOptional.ofNullable(myMap.get(myKey));
Given the example you've provided, it seems that you want to apply the operation foo.add if bar is present otherwise return foo:
Foo foobar = bar.isPresent() ? foo.add(bar.get()) : foo;
Thus, I'd say it's so short that it's not worthy of creating a utility method for it.
Foo foobar = optBar.map(f::add).orElse(f); // map to Foo if bar is present else return `f`
- if
optBarhas a present state, we apply themapoperation andorElsereturns that mapped value. - if
optBarhas an absent state, theorElsemethod returns the supplied default valuef.
Another thing, are you getting the result as an Optional<Bar> in the first place or are you manually wrapping Bar into an Optional? if it's the latter I'd probably just use a simple if statement which would be the ideal solution, i.e.
Foo foo = new Foo();
if(bar != null) foo = foo.add(bar);
Using bar rather than foo seems to simplify it:
Foo foobar = bar
.map(b -> foo.map(f -> f.add(b)))
.orElse(foo)
.orElse(null); // if foo is not present
bar.map(b -> foo.map(f -> f.add(b))) returns Optional<Optional<Foo>> that is "present" if bar is present.
.orElse(foo) reverts to the original Optional<Foo> if bar was not present (or returns foo.map(f -> f.add(b)) otherwise).
The whole chain of operations returns a String:
- The first step (
map(...)) maps theOptional<User>to anOptional<String>. - The second step (
orElseThrow(...)) unwraps theOptional<String>, thus returning aString(or throwing anIllegalArgumentException, if empty).
We can find the source code of Optional::map here.
You are totally correct. The map() method returns an Optional, and I applaud your use of the javadoc. The difference here is that you then invoke the orElseThrow() method on that Optional that map() returned. If you refer to the javadoc for orElseThrow(), you will see that it returns "the present value [of the Optional]". In this case, that is a String.
Use map if the function returns the object you need or flatMap if the function returns an Optional. For example:
public static void main(String[] args) {
Optional<String> s = Optional.of("input");
System.out.println(s.map(Test::getOutput));
System.out.println(s.flatMap(Test::getOutputOpt));
}
static String getOutput(String input) {
return input == null ? null : "output for " + input;
}
static Optional<String> getOutputOpt(String input) {
return input == null ? Optional.empty() : Optional.of("output for " + input);
}
Both print statements print the same thing.
They both take a function from the type of the optional to something.
map() applies the function "as is" on the optional you have:
if (optional.isEmpty()) return Optional.empty();
else return Optional.of(f(optional.get()));
What happens if your function is a function from T -> Optional<U>?
Your result is now an Optional<Optional<U>>!
That's what flatMap() is about: if your function already returns an Optional, flatMap() is a bit smarter and doesn't double wrap it, returning Optional<U>.
It's the composition of two functional idioms: map and flatten.