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
|
ifPresent 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
Return the value if present, otherwise return
|
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
orElseGet
Return the value if present, otherwise invoke
|
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) ;
}
}