preface

Before Java8, when writing code, we often encountered a NullPointerException(NPE) if this situation was left unchecked. In Java8, the Optional type is a better representation of the missing return value.

Let’s start with a piece of code, which is probably how most people used to write it

private void getIsoCode( User user){

  if(user ! =null) {

    Address address = user.getAddress();

    if(address ! =null) {

      Country country = address.getCountry();

      if(country ! =null) {

          String isocode = country.getIsocode();

          if(isocode ! =null) {

              isocode = isocode.toUpperCase();

          }

      }

    }

  }

}

Copy the code

But when we add Optional, we can cut that down a lot, and I’ll give you the answer later.

I’ve seen people write it like this

Optional<T> optionalValue = ... ;

optionalValue.get().someMethod();



or



if(optionalValue.isPresent()) {

  optionalValue.get().someMethod();

}

Copy the code

It is no safer than the following

T value = ... ;

value.someMethod();



or



if(value ! =null) {

  value.someMethod();

}

Copy the code

If you have a snippet in your code that uses Optional above, it’s time to optimize.

The key to using Optional efficiently is to use a method that either accepts the correct value or returns another alternative value.

Create the Optional

// Create an empty Optional instance

public static<T> Optional<T> empty(a) {

  Optional<T> t = (Optional<T>) EMPTY;

  return t;

}



// Create a non-empty instance based on the passed value. Value cannot be empty or an NPE will be thrown

 public static <T> Optional<T> of(T value) {

  return new Optional<>(value);

}



// Create an instance from the value passed in. Value can be null

public static <T> Optional<T> ofNullable(T value) {

  return value == null ? empty() : of(value);

}

Copy the code

The above three methods are how we construct Optional, and you can see that Optional is actually a wrapper around value. Note the difference between ofNullable and of. OfNullable is recommended

Other Common methods

  1. Boolean isPresent() Checks whether value exists

  2. Optional filter(Predicate Predicate) Determines whether the value meets the conditions

  3. Optional map(Function
    mapper) performs a function on its value to change it to another value. The returned value is encapsulated by optional. ofNullable

  4. Optional flatMap(Function
    > mapper) returns a value of Optional type. The value returned by this function is not encapsulated.

  5. OrElse (T other) Returns value if value exists and other if it does not

  6. orElseGet(Supplier
    other) is the same as orElse, except that the parameters are determined by passing function

  7. T orElseThrow Returns value if value exists and throws an exception if it does not

Code optimization

The code given at the beginning can be optimized for the following code

 String isoCode = Optional.ofNullable(user)

    .map(User::getAddress)  //Optional<Address>

    .map(Address::getCountry)  //Optional<Country>

    .map(Country::getIsocode)  // Optional<String>

    .orElse("empty");

Copy the code

However, the difference between orElse and orElseGet is that methods in orElse are always executed whether or not conditions are met, while methods in orElse are executed only when value is null.

Optional.ofNullable(user)

    .map(User::getAddress)

    .map(Address::getCountry)

    .map(Country::getIsocode)

    .orElse(getIsoCode());

Copy the code

You might not think much of it, but if your business needs to query the database to get this value, then every time you run this code, you’re going to have to query it, and you’re going to lose unnecessary performance, and that’s a big problem.

Technical summary

  1. Optional is intended to be a more elegant way to determine null, but it does not necessarily mean that where null exists, Optional should be used instead
  2. Optional is generally used for method return values, not properties (cannot be serialized)
  3. Optional works wonders for multi-level NULL judgments