Using Optional to Prevent Null Checking

We’ve all written (or at least seen) code like this:

if(myObject != null) {
    myObject.callSomeMethod();
}

Null checking, if left unchecked (!), can grow out of control. Fortunately, there are ways to structure your code to avoid too many null checks. For instance, keeping all null checks at the boundaries of your application lets the rest of the code presume no nulls. Additionally, judicious use of the Null Object Pattern can help to keep things clean.

Keeping those techniques in mind, we can do even more to prevent null checks from cluttering our code: Java’s Optional class.

Oracle has an excellent article explaining how to use Optional to circumvent null checking, and I recommend reading it. My blog post here is not intended to replace that article. I just want to do a little exposition about using it in a real world scenario.

In a recent blog post we were talking about implementing a HashMap. We don’t need to rehash (!) all the details here, but here’s a quick explanation of one method in particular:

private LinkedList<Entry<K,V>> getElementList(K searchKey) {
   int index = searchKey.hashCode() % elements.length;
   if(elements[index] == null) {
      elements[index] = new LinkedList<>();
   }
   return elements[index];
}

In english: we’re calculating the index of an array of lists, and if the array at that index has a list in it we return the list. Further, if that index is empty we create a new list, assign it to that element in the array, and return it. One way to circumvent the null check is to initialize the array with new lists before we start using it. But we might not want to do that if we want our map not to allocate too much memory up front, or to be faster to initialize.

This is a short method, but can we do better? How about using the ternary operator to reduce the check to a one-liner:

private LinkedList<Entry<K,V>> getElementList(K searchKey) {
   int index = searchKey.hashCode() % elements.length;
   elements[index] = (elements[index] == null) ? new LinkedList<>() : elements[index];
   return elements[index];
}

It’s more concise, sure, but the complexity is the same (the method has a cyclomatic complexity of 2 because there are two logical paths through the method). Can we do better? Using Apache Commons ObjectUtils lets us reduce the cyclomatic complexity to 1 since there is only one path through the method.

private LinkedList<Entry<K,V>> getElementList(K searchKey) {
   int index = searchKey.hashCode() % elements.length;
   elements[index] = (LinkedList<Entry<K,V>>)ObjectUtils.defaultIfNull(elements[index], new LinkedList<>());
   return elements[index];
}

The cyclomatic complexity has been reduced, but a new object (the new LinkedList()) is instantiated each time whether we need it or not. Can we do better? We can use Optional with a lambda (here, () -> new LinkedList()) which is only called if the element is not present.

private LinkedList<Entry<K,V>> getElementList(K searchKey) {
   int index = searchKey.hashCode() % elements.length;
   elements[index] = Optional.ofNullable(elements[index]).orElseGet(() -> new LinkedList<>());
   return elements[index];
}

Finally we are using Optional for its intended use case!

So at this point we have:

  • eliminated null check from three lines to one
  • reduced complexity from two to one
  • only instantiate the new list if it’s actually needed.

Not bad for using Optional in the wild! Hopefully things gives a small taste of how useful Optional can be.

Advertisements

Leave a comment

Filed under Software Engineering

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s