1. Overview

Optional is a class that was introduced in Java 8 as part of the java.util package. It serves as a container that may or may not contain a non-null value. Optional can help us handle null values more effectively and avoid NullPointerExceptions in our code.

One common task when working with Optional is to check if it contains a value equal to a specific object. In this tutorial, we’ll explore various techniques for performing this check.

2. Introduction to the Problem

First, let’s clarify the requirement of the equality check. Let’s say we have two objects; one is a non-null valueOfT object of type T, and the other one is an opt instance of type Optional.

If opt is empty, it doesn’t contain any value. That is to say, the value inside it cannot be equal to any target object, so the check will always return false. Conversely, if opt is “present”, we need to verify whether the value carried by opt is equal to valueOfT.

So, simply put, we’ll perform an “opt present and equals valueOfT” check.

In this tutorial, we’ll explore various methods to accomplish the task. To keep things straightforward, we’ll use String as an example of T to demonstrate each approach. Let’s create two String constants:

static final String A_B_C = "a b c";
static final String X_Y_Z = "x y z";

We’ll use these String values in unit tests to showcase the results of different methods.

Next, let’s dive into the code and examine how to implement the check.

3. Using *Optional.*equals()

The Optional class has overridden the equals() method. If two Optional objects are present and the values they hold are equal, the method returns true. Therefore, we can first create an Optional instance from valueOfT, and then perform the check using Optional.equals() with the given opt object:

opt.isPresent() && opt.equals(Optional.of(valueOfT));

Next, let’s check whether this approach works as expected.

First, let’s look at opt‘s absent case:

Optional<String> opt = Optional.empty();
assertFalse(opt.isPresent() && opt.equals(Optional.of(A_B_C)));

As we mentioned, if opt is empty, no matter what value valueOfT has, the entire check should return false.

Next, let’s see if this approach produces the expected result when opt is present:

opt = Optional.of(X_Y_Z);
assertFalse(opt.isPresent() && opt.equals(Optional.of(A_B_C)));
 
opt = Optional.of(A_B_C);
assertTrue(opt.isPresent() && opt.equals(Optional.of(A_B_C)));

As we can see, this approach solves the problem, but it creates an intermediate Optional object.

4. Using Optional.get()

A straightforward approach to checking whether the value contained in opt equals valueOfT is first to retrieve the value in opt using Optional.get(), and then verify its equality with valueOfT:

opt.isPresent() && opt.get().equals(valueOfT);

Next, let’s follow this pattern and use the same inputs to verify whether it yields correct results:

Optional<String> opt = Optional.empty();
assertFalse(opt.isPresent() && opt.get().equals(A_B_C));
 
opt = Optional.of(X_Y_Z);
assertFalse(opt.isPresent() && opt.get().equals(A_B_C));
 
opt = Optional.of(A_B_C);
assertTrue(opt.isPresent() && opt.get().equals(A_B_C));

As the code shows, this solution doesn’t create extra objects.

5. Using Optional.map() and Optional.orElse()

We expect to obtain a boolean value after the “opt present and equals valueOfT” check. Hence, we can perceive this problem as converting an Optional object to a boolean by adhering to a certain rule.

The Optional class provides map() to transform a present Optional to another Optional carrying a different value.

Moreover, the orElse() method returns the value wrapped by the Optional instance if it’s present. Otherwise, if the Optional is empty, orElse() returns the value we specify.

So, we can combine these two methods to perform the equality check and obtain a boolean from the given Optional:

opt.map(v -> v.equals(valueOfT)).orElse(false);

Next, let’s see if it works with our inputs:

Optional<String> opt = Optional.empty();
assertFalse(opt.map(A_B_C::equals).orElse(false));
 
opt = Optional.of(X_Y_Z);
assertFalse(opt.map(A_B_C::equals).orElse(false));
 
opt = Optional.of(A_B_C);
assertTrue(opt.map(A_B_C::equals).orElse(false));

This solution also results in an intermediate object, created by the Optional object map(). However, it’s a functional and fluent approach.

6. Conclusion

In this article, we explored three ways to check if an Optional contains a value equal to a specific object. These methods allow us to perform null-safe value comparison operations on Optional instances, ensuring robust and error-free code.

As always, the complete source code for the examples is available over on GitHub.