I used the Optional class for a library I am writing. There
are not many good introductions to it so I thought of writing something here.
We may view the optional as a container that might have something in it (a
value) or it might be empty. This comes in handy if you are expecting a null
or empty value
public
class
DoubleIt {
public
static
Optional<Integer> twice(Integer score){
if
(score==null) return
Optional.empty();
return
Optional.of(score*2);
}
public
static
void
main(String[] args) {
out.println(twice(100));
out.println(twice(null));
}
}
// output : “Optional[200]”
// output : “Optional.empty”
Normally we want to check if the value is there or not. This is how we will
likely check:
// retrieve value
Optional<Integer> a= twice(100);
if
(a.isPresent()) out.println("Double straight : "
+ a.get());
// if calling .get on empty then we get an error
java.util.NoSuchElementException
// output: Double straight : 200
So now that we know how to retrieve a value we see that there may be a pattern
emerging. We may write the same method twice as in above in a single
line so:
import
java.util.Optional;
import
java.util.function.Supplier;
import
static
java.lang.System.out;
public
class
DoubleIt {
public
static
Optional<Integer> twiceBrief(Integer score){// using ternary operator
Optional o
= (score==null)? Optional.empty(): Optional.of(score*2);
return
o;
}
public
static
void
main(String[] args) {
// brief
Optional<Integer> abrf= twiceBrief(100);
if
(abrf.isPresent()) out.println("Double with ternary operator : "
+ abrf.get());
// output: Double with ternary operator : 200
}
}
Since the above is a pattern there is a provided method for dealing with the
above scenario.
import
java.util.Optional;
import
java.util.function.Supplier;
import
static
java.lang.System.out;
public
class
DoubleIt {
public
static
Optional<Integer> twiceBriefer(Integer score){
return
Optional.ofNullable(score*2); // same as twiceBrief and twice
}
public
static
void
main(String[] args) {
//briefer
Optional<Integer> abrfr= twiceBriefer(100);
if
(abrfr.isPresent()) out.println("Double using ofNullable : "+abrfr.get());
// output: Double using ofNullable : 200
}
}
Following are some of the methods that may be helpful in the Optional class
API.
ifPresent
void
|
ifPresent(Consumer<? super
T> consumer)
If a value is present, invoke the specified consumer with the
value, otherwise do nothing.
|
Now using
ifPresent:
public
class
DoubleIt {
public
static
Optional<Integer> twice(Integer score){
if
(score==null) return
Optional.empty();
return
Optional.of(score*2);
}
public
static
void
main(String[] args) {
// using ifPresent
Optional<Integer> aalt
= twice(500);
// in the following a consumer consumes a value
aalt.ifPresent(out::println);
// out::println is same as : str ->
System.out.println(str)
// output: 1000
}
}
orElse
T
|
orElse(T other)
Return the value if present, otherwise return
other .
|
What if a value is not present:
public
class
DoubleIt {
public
static
Optional<Integer> twice(Integer score){
if
(score==null) return
Optional.empty();
return
Optional.of(score*2);
}
public
static
void
main(String[] args) {
// what if a value is NOT present
Optional<Integer> ae= twice(null);
out.println("When empty return 0 : "+ae.orElse(0));
// output : When empty return 0 : 0
}
}
orElseGet
T
|
orElseGet(Supplier<? extends
T> other)
Return the value if present, otherwise invoke
other
and return the result of that invocation.
|
Following allows you to invoke a supplier method & return the result.
public
class
DoubleIt {
public
static
Optional<Integer> twice(Integer score){
if
(score==null) return
Optional.empty();
return
Optional.of(score*2);
}
public
static
void
main(String[] args) {
out.println("When empty return some random calculation : "
+ae.orElseGet( () -> ( (int)( Math.random() * 1000) ) )
);
// with further elaboration on the supplier function
out.println("When empty return some random calculation too : "
+ae.orElseGet( () -> {
out.println("Inside the supplier lambda function");
return
(int)( Math.random() * 1000) ;
}
)
) ;
}
}
You may refactor out the supplier method so:
import
java.util.Optional;
import
java.util.function.Supplier;
import
static
java.lang.System.out;
public
class
DoubleIt {
public
static
void
main(String[] args) {
// separate supplier method refactored out
Supplier<Integer> m
= () ->{
out.println("Inside the separately defined supplier lambda function");
return
(int)( Math.random() * 1000) ;
};
out.println("When empty return some random calculation : "+ae.orElseGet(m) ) ;
}
}
Or you may have the supplier method at class level instead of at method level:
import
java.util.Optional;
import
java.util.function.Supplier;
import
static
java.lang.System.out;
public
class
DoubleIt {
public
static
void
main(String[] args) {
//
out.println("When empty return some random calculation : "
+ae.orElseGet(DoubleIt::r ) ) ;
}
public
static
Integer r() {
out.println("Inside the separately defined static supplier method ");
return
(int)( Math.random() * 1000) ;
}
}