Course – LS – All

Get started with Spring and Spring Boot, through the Learn Spring course:

>> CHECK OUT THE COURSE

1. Overview

In this tutorial, we’ll learn how to return the first non-null element from a list or sequence of data.

We’ll also explore lazy evaluation when returning the first non-null from a chain of expensive methods. Finally, we’ll discover how the use of the Optional class will require us to return the first non-empty Optional instead.

2. for Loop

Before the introduction of functional programming in Java 8, it was common to use a for loop to return the first non-null element from a list.

Let’s consider a list with null for the first element:

List<String> objects = Arrays.asList(
    null,
    "first non null",
    "second non null"
);

To return the first non-null element, we could use a traditional for loop to iterate and check each element for nullability via a simple if statement:

String object = null; 
for (int i = 0; i < objects.size(); i++) {
    if (objects.get(i) != null) {
        object = objects.get(i);
        break;
    }
}

3. Stream API

With the introduction of the Stream API in Java 8, we’re now able to accomplish many common patterns in a more readable, simplistic, and declarative fashion.

To find the first non-null element, we stream our list sequentially by invoking the stream() method and search for the first non-null element:

Optional<String> object = objects
  .stream()
  .filter(o -> o != null)
  .findFirst();

We use the intermediate filter() operation to filter our stream based on a Predicate, which in our case is a simple null check lambda o -> o! = null. Finally, we invoke the terminal findFirst() operation to return the first element that satisfied the preceding operations or an empty Optional.

In pursuit of enhanced readability, we could instead use Objects.nonNull() as a method reference in place of the lambda expression:

Optional<String> object = objects
  .stream()
  .filter(Objects::nonNull)
  .findFirst();

4. Lazy Evaluation of Methods That May Return null

Throughout this article, we’ve assumed that we want to return the first non-null item from a sequence of data that’s readily available. But what if the methods used to obtain our values are expensive to evaluate? Instead, we may want to lazily evaluate a sequential chain of methods until we obtain the first non-null for performance reasons.

Let’s consider the following methods, which we’ll pretend are expensive to compute:

String methodA() {
    return null;
}

String methodB() {
    return "first non null";
}

String methodC() {
    return "second non null";
}

Before Java 8, we may have used a series of if statements:

String object = methodA();
if (object == null) {
    object = methodB();
}

if (object == null) {
    object = methodC();
}

With the Stream API, we can take advantage of the functional interface Supplier to achieve lazy evaluation of our methods:

Optional<String> object = Stream
  .<Supplier<String>>of(
      this::methodA, 
      this::methodB,
      this::methodC)
  .map(Supplier::get)
  .filter(Objects::nonNull)
  .findFirst();

In our stream pipeline, an expensive method is only evaluated when get() is invoked on the Supplier function object as part of the map() operation. We ensure lazy evaluation by using a sequential stream. Each stream element is checked by the intermediate filter() condition and the stream terminates as soon as we find the first non-null element that satisfies the condition.

5. External Libraries

Instead of writing our own implementations, we can also leverage popular external libraries that address the issue.

5.1. Apache Commons Lang 3

To use Apache Commons Lang 3, we need to add the following dependency to our pom.xml:

<dependency> 
    <groupId>org.apache.commons</groupId> 
    <artifactId>commons-lang3</artifactId> 
    <version>3.14.0</version> 
</dependency>

Given a single reference which may or may not be null, we can use ObjectUtils.getIfNull() to obtain the value if it’s non-null or return the value from an alternative method that’s lazily evaluated:

ObjectUtils.getIfNull(object, this::methodB);

Given a list of objects, we can utilize ObjectUtils.firstNonNull() which takes a varargs:

@Test
void givenListOfObjects_whenUsingApacheCommonsLang3_thenReturnFirstNonNull() {
    String object = ObjectUtils.firstNonNull(objects.toArray(new String[0]));

    assertEquals("first non null", object);
}

If all the arguments are null, then null is returned.

Further, we can also lazily evaluate our nullable methods with ObjectUtils.getFirstNonNull():

ObjectUtils.getFirstNonNull(this::methodA, this::methodB, this::methodC);

5.2. Google Guava

To use Google Guava, we need to add the following dependency to our pom.xml:

<dependency> 
    <groupId>com.google.guava</groupId> 
    <artifactId>guava</artifactId> 
    <version>32.1.3-jre</version> 
</dependency>

Given two references, we can use MoreObjects.firstNonNull():

@Test
void givenTwoObjects_whenUsingGoogleGuavaMoreObjects_thenReturnFirstNonNull() {
    String nullObject = null;
    String nonNullObject = "first non null";
    String object = MoreObjects.firstNonNull(nullObject, nonNullObject);

    assertEquals("first non null", object);
}

However, if both arguments are null then a NullPointerExecption is thrown.

Given a list, we can return the first non-null using Iterables.find() with Predicates.nonNull():

@Test
void givenListOfObjects_whenUsingGoogleGuavaIterables_thenReturnFirstNonNull() {
    String object = Iterables.find(objects, Predicates.notNull());

    assertEquals("first non null", object);
}

6. Optional

This article would be amiss if it didn’t mention the use of the Optional type. This class was introduced in Java 8 specifically to address the shortcomings of null references.

The Optional type allows developers to signify explicitly that a method or variable may or may not have a value. As a result, our methods which previously returned a null or value now return an Optional instead.

Thus, our previous problem of ‘returning the first non-null value’ transformed into a subtly different problem. How do we return the first non-empty Optional?

Let’s consider the following list that has an empty first element:

List<Optional<String>> optionals = Arrays.asList(
    Optional.<String> empty(), 
    Optional.of("first non empty"), 
    Optional.of("second non empty")
);

We can stream our list and search for the first non-empty element:

@Test
void givenListOfOptionals_whenStreaming_thenReturnFirstNonEmpty() {
    Optional<String> object = optionals.stream()
      .filter(Optional::isPresent)
      .map(Optional::get)
      .findFirst();

    assertThat(object).contains("first non empty");
}

We check if each given Optional has a value using the ifPresent() method. If an element satisfies this predicate, then we can safely obtain the value using get() as part of the map() intermediate operation.

7. Conclusion

In this article, we’ve explored how to return the first non-null using our own implementations as well as external libraries.

We’ve also considered lazily evaluation when we want to return the first non-null from a chain of expensive methods.

Finally, we’ve also demonstrated how to return the first non-empty Optional as this may be a more appropriate use case since its introduction in Java 8.

The code samples used in this article can be found over on GitHub.

Course – LS – All

Get started with Spring and Spring Boot, through the Learn Spring course:

>> CHECK OUT THE COURSE
res – REST with Spring (eBook) (everywhere)
2 Comments
Oldest
Newest
Inline Feedbacks
View all comments
Comments are closed on this article!