How to use Optional In Java

  • Post last modified:December 15, 2022
  • Reading time:4 mins read
Photo by Kelly Sikkema on Unsplash

Introduction

  • In this article i we will discuss why we should avoid using Null and start using Optional as much as possible.
  • Also we will see how to handle situation when we don’t have and element or we are having nothing/empty.

Problems with Null

  • In Java, whenever we don’t have anything to return we often end up in returning null .
  • But returning null brings lot of problem to the client who is consuming that results.
  • Now they have to do null check for each object whether it is returning null or not and its adds lot of boilerplate which doesn’t make our code look good.
  • If we as a developer forget to handle the null check, our code is end up throwing NullPointerException.
// optional empty, only prints if element present
Optional<String> email1 = Optional.empty();
email1.stream().forEach(System.out::println); 
// throws null pointer exception if we return null for nothing.
String email2 = null;
System.out.println(email2.length());

Optional To Rescue

  • Optional is just nice little wrapper that provides us method isPresent(), which allows to do quick check if the element that we want to use is present or not, if yes then code executes otherwise code doesn’t executes at all.
public static void main(String[] args) {
    OptionalInt optionalInt = generateId();
    optionalInt.ifPresent(System.out::println);
}
private static OptionalInt generateId(){
    OptionalInt max = new Random().ints().limit(5).max();
    return max;
}

Creating Optional

  • Optional class provides 3 static methods to generate Optional object.

Of(T value)

  • We can create optional of element by passing single argument of type T.
Optional<Integer> integer = Optional.of(1)

OfNullable( T value )

  • We can create optional of nullable as well. Only difference between these two is if the argument is null then ofNullable returns empty optional, while of(null) throws NullPointerException
Optional<Integer> integer = Optional.of(1);
Optional<Integer> integer1 = Optional.ofNullable(null);
System.out.println(integer);
System.out.println(integer1);

Retrieve value from Optional

  • get():
    This method returns the value of optional if present otherwise it returns NoSuchElement exception
Optional<Integer> integer = Optional.of(1);
System.out.println(integer.get());
  • orElse(T value);
    If value is present in optional then it get that value or its return specified value in orElse.
Optional<Integer> integer1 = Optional.ofNullable(null);
System.out.println(integer1);
System.out.println(integer1.orElse(1));
  • orElseGet(Supplier<? extends T> other)
    If optional is present then it get that value , otherwise ElseGet return Supplier that we provide as argument.
Optional<Integer> integer1 = Optional.ofNullable(null);
System.out.println(integer1.orElseGet(()->new Random().nextInt()));
Optional<Integer> integer1 = Optional.ofNullable(123);
System.out.println(integer1.orElseGet(()->new Random().nextInt()));
  • orElseThrow(Supplier<? extends X> exceptionSupplier)
    If option is empty then we can return supplier as exception.
Optional<String> names = Optional.ofNullable(null);
names.orElseThrow(IllegalArgumentException::new);

Optional Usage in Java Streams

  • Many of java streams operation returns Optional value. for example, below example streams operation returning OptionalInt since after filter operation their maybe element or maybe not. 
  • As a developer we should also take the same approach , whenever we are not sure if the element would be returned guaranteed , we should return optional. It gives good idea to consumer of the code to what to expect in return.
Stream<Integer> integer = Stream.of(1, 2, 3, 4);
OptionalInt max = integer.filter(i->i%2==0).mapToInt(a->a).max();
max.ifPresent(System.out::println);
  • Below is another example where we have names stream, then we perform terminate operation that takes comparator as argument and return the Optional of string.
  • We can either have max length string or not. It may be the case where our stream might be empty.
Stream<String> names = Stream.of("sam", "dann", "dd");
Optional<String> maxNames = names.max((a,b)->a.length()-b.length());
maxNames.ifPresent(System.out::println);

Conclusion

  • In this article we used Optional to avoid returning Null objects and explored various method to handle null or empty values gracefully.

Bonus Tip

Leave a Reply