
In Java 8, a new class named Optional was introduced. Or rather in the word-style of Douglas Adams, “in the beginning null was created. This made a lot of people angry and was widely regarded as a bad move“. Optional was introduced to alleviate some of that anger.
Optional relieved developers of the grief of null checks and the “fun” of a NullPointerException popping up when failing to null check.
In Java 8, the Optional already had very useful methods:
of– Wrap the non-null value into anOptional.ofNullable– Wrap and return anOptionalof the current value, if current value is null, returnOptional.empty()isPresent– Checks and returns a boolean indicating the presence of a non-null value in theOptional.ifPresent– Checks and invokes the specifiedConsumerinstance upon the presence of a non-null value in theOptional.get– Fetch the value in theOptionalif it is not null, else throw aNoSuchElementExceptionorElse– Fetch the value in theOptionalif it is not null, else return the other element passed in.orElseGet– Fetch the value in theOptionalif it is not null, else return invoke the otherSupplierto fetch an element instead.orElseThrow– Fetch the value in theOptionalif it is not null, else throw the passed inException.filter– If the value exists, test the filteringPredicateon it and if true return result wrapped in anOptional, else returnOptional.empty().map– If the value exists, apply the mappingFunctionto it and return any non-null result wrapped in anOptional, else returnOptional.empty().flatMap– If the value exists, apply theOptional-bearing mappingFunctionto it and return any non-null result wrapped in anOptional, else returnOptional.empty().
Java 9 changes
ifPresentOrElse– Checks and returns a boolean indicating the presence of a non-null value in theOptional, or else, invokes theRunnableaction.or– Wrap and return anOptionalof the current value if not null; if current value is null, returnOptionalby invoking the specifiedSupplierstream– Returns a sequential stream containing only the value, if the value is non-null.
Optional::ifPresentOrElse
Consider a situation where the code is to either run a Consumer if the value exists or else run a different action. This is not possible in the Java 8 Optional behavior. Optional in Java 8 provides an orElse or an orElseGet method, both of which actually return an unwrapped value, rather than act as an execution block.
Pre-Java 8 :
if(preference != null) {
callPresenceAction();
} else {
callAbsenceAction();
}
In Java 8 :
if(optionalPreference.isPresent()) {
callPresenceAction();
} else {
callAbsenceAction();
}
or
optionalPreference.ifPresent(callPresenceConsumer());
// orElseGet returns a non-optional value
// it cannot be used to simply execute an action.
Preference p = optionalPreference.orElseGet(callAbsenceSupplier());
In Java 9 :
optionalPreference
.ifPresentOrElse(presenceAction,absenceAction);
Optional::or
Per the Java 8 API, both the orElse and the orElseGet do not return an Optional, rather return the unwrapped value. It is possible that such a value is null. The or method is introduced as a means to execute a supplier on absence of an unwrapped value in the container, and returns an Optional, rather than the unwrapped value.
Pre-Java 8 :
Preference preference = findPreference(name);
if(preference == null) {
preference = createPreference(name, description);
}
// preference can still be null !!!
In Java 8 :
Preference preference =
findOptionalPreference(name)
.orElseGet(getPreferenceSupplier(name, description));
// preference can still be null !!!
In Java 9 :
Optional optionalPreference =
findOptionalPreference(name)
.or(getOptionalPreferenceSupplier(name, description));
// optional preference, so, protected from being null !!!
Optional::stream
Given a situation where a stream or collection of Optionals exist, and we need to extract values from each, if they contain non-null values. Optional::stream returns a stream with a single non-null value if the Optional has a non-null value, or returns an empty stream otherwise.
Pre-Java 8 :
List preferences = new ArrayList();
for (String preferenceName : PREFERENCE_NAMES) {
Preference aPreference = findPreference(preferenceName);
if (aPreference != null) {
preferences.add(aPreference);
}
}
In Java 8 :
List preferences =
PREFERENCE_NAMES.stream()
.map(preferenceName -> findOptionalPreference(preferenceName))
.filter(Optional::isPresent)
.map(Optional::get)
.collect(toList());
In Java 9 :
List preferences =
PREFERENCE_NAMES.stream()
.map(preferenceName -> findOptionalPreference(preferenceName))
.flatMap(Optional::stream)
.collect(toList());
That’s a wrap on the Optional changes in Java 9. Hope this post was helpful.
