Partner – Microsoft – NPI (cat=Java)
announcement - icon

Microsoft JDConf 2024 conference is getting closer, on March 27th and 28th. Simply put, it's a free virtual event to learn about the newest developments in Java, Cloud, and AI.

Josh Long and Mark Heckler are kicking things off in the keynote, so it's definitely going to be both highly useful and quite practical.

This year’s theme is focused on developer productivity and how these technologies transform how we work, build, integrate, and modernize applications.

For the full conference agenda and speaker lineup, you can explore JDConf.com:

>> RSVP Now

1. Introduction

In some cases, we might want to fallback to another Optional instance if another one is empty.

In this tutorial, we’ll briefly mention how we can do that – which is harder than it looks.

For an introduction to the Java Optional class, have a look at our previous article.

2. Java 8

In Java 8, there’s no direct way to achieve return a different Optional if the first one is empty.

Therefore, we can implement our own custom method:

public static <T> Optional<T> or(Optional<T> optional, Optional<T> fallback) {
    return optional.isPresent() ? optional : fallback;
}

And, in practice:

@Test
public void givenOptional_whenValue_thenOptionalGeneralMethod() {
    String name = "Filan Fisteku";
    String missingOptional = "Name not provided";
    Optional<String> optionalString = Optional.ofNullable(name);
    Optional<String> fallbackOptionalString = Optional.ofNullable(missingOptional);
 
    assertEquals(
      optionalString, 
      Optionals.or(optionalString, fallbackOptionalString));
}
    
@Test
public void givenEmptyOptional_whenValue_thenOptionalGeneralMethod() {
    Optional<String> optionalString = Optional.empty();
    Optional<String> fallbackOptionalString = Optional.ofNullable("Name not provided");
 
    assertEquals(
      fallbackOptionalString, 
      Optionals.or(optionalString, fallbackOptionalString));
}

2.1. Lazy Evaluation

The above solution has one serious drawback – we need to evaluate both Optional variables before using our custom or() method.

Imagine, we have two methods returning Optionals, both querying database under the hood. It would be unacceptable, from the performance point of view, to call both of them if already the first method returns the value we need.

Let’s create a simple ItemsProvider class:

public class ItemsProvider {
    public Optional<String> getNail(){
        System.out.println("Returning a nail");
        return Optional.of("nail");
    }

    public Optional<String> getHammer(){
        System.out.println("Returning a hammer");
        return Optional.of("hammer");
    }
}

Here’s how we can chain these methods and take advantage of lazy evaluation:

@Test
public void givenTwoOptionalMethods_whenFirstNonEmpty_thenSecondNotEvaluated() {
    ItemsProvider itemsProvider = new ItemsProvider();

    Optional<String> item = itemsProvider.getNail()
            .map(Optional::of)
            .orElseGet(itemsProvider::getHammer);

    assertEquals(Optional.of("nail"), item);
}

The above test case prints only “Returning a nail”. This clearly indicates that only the getNail() method has been executed.

3. Java 9

Java 9 has added an or() method that we can use to get an Optional, or another value, if that Optional isn’t present.

Let’s see this in practice with a quick example:

public static Optional<String> getName(Optional<String> name) {
    return name.or(() -> getCustomMessage());
}

We’ve used an auxiliary method to help us with our example:

private static Optional<String> getCustomMessage() {
    return Optional.of("Name not provided");
}

We can test it and further understand how it’s working. The following test case is a demonstration of the case when Optional has a value:

@Test
public void givenOptional_whenValue_thenOptional() {
    String name = "Filan Fisteku";
    Optional<String> optionalString = Optional.ofNullable(name);
    assertEquals(optionalString, Optionals.getName(optionalString));
}

4. Using Guava

Another way to do this is by using or() method of the guava’s Optional class. First, we need to add guava in our project (the latest version can be found here):

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

Now, we can continue with the same example that we had earlier:

public static com.google.common.base.Optional<String> 
  getOptionalGuavaName(com.google.common.base.Optional<String> name) {
    return name.or(getCustomMessageGuava());
}
private static com.google.common.base.Optional<String> getCustomMessageGuava() {
    return com.google.common.base.Optional.of("Name not provided");
}

As we can see, it’s very similar to the one displayed above. However, it has a slight difference in the naming of the method and is exactly the same as or() method of the class Optional from JDK 9.

We can now test it, similarly as the example above:

@Test
public void givenGuavaOptional_whenInvoke_thenOptional() {
    String name = "Filan Fisteku";
    Optional<String> stringOptional = Optional.of(name);
 
    assertEquals(name, Optionals.getOptionalGuavaName(stringOptional));
}
@Test
public void givenGuavaOptional_whenNull_thenDefaultText() {
    assertEquals(
      com.google.common.base.Optional.of("Name not provided"), 
      Optionals.getOptionalGuavaName(com.google.common.base.Optional.fromNullable(null)));
}

5. Conclusion

This was a quick article illustrating how to achieve Optional orElse Optional functionality.

The code for all the examples explained here, and much more can be found over on GitHub.

Course – LS (cat=Java)

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

>> CHECK OUT THE COURSE
res – REST with Spring (eBook) (everywhere)
Comments are closed on this article!