Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Learn Handling Values with the Optional Class | Terminal Operations in the Stream API
Stream API
course content

Course Content

Stream API

Stream API

1. Fundamentals and Functional Capabilities of Stream API
4. Practical Applications of Stream API

book
Handling Values with the Optional Class

In Java, variables that store objects can hold a null value. This often leads to NullPointerException if null isn't handled properly. These errors make code less reliable and harder to maintain. This is where Optional comes in.

Think of it as a box—it may contain a value, or it may be empty. Instead of using if statements to check for null, you work with this "box" and use convenient methods to safely retrieve the value if it exists.

Syntax and Usage of Optional

The main goal of Optional is to avoid NullPointerException by replacing standard if (value != null) checks with more readable methods.

There are three ways to create an Optional:

  • Optional.empty() – creates an empty Optional with no value;
  • Optional.of(value) – wraps the given object, but only if it's guaranteed to be non-null;
  • Optional.ofNullable(value) – wraps the object, even if it's null, creating either a populated Optional or an empty one.
java

Main

copy
123456789101112131415
package com.example; import java.util.Optional; public class Main { public static void main(String[] args) { Optional<String> emptyOpt = Optional.empty(); Optional<String> optWithValue = Optional.of("Laptop"); Optional<String> optNullable = Optional.ofNullable(null); System.out.println("Empty Optional: " + emptyOpt); System.out.println("Optional with value: " + optWithValue); System.out.println("Optional with null: " + optNullable); } }

If you pass null to Optional.of(value), the program will throw a NullPointerException, so ofNullable() should always be used for potentially empty values.

Retrieving Values from Optional

To extract a value from an Optional, you can use the get() method.

java

Main

copy
12345678910
package com.example; import java.util.Optional; public class Main { public static void main(String[] args) { Optional<String> optWithValue = Optional.of("Laptop"); System.out.println("Final string: " + optWithValue.get()); } }

Here, get() returns the actual object stored inside the Optional. However, if the Optional is empty (contains null), calling get() will throw a NoSuchElementException.

Checking for a Value

When working with Optional, you need to check if it contains a value. One way to do this is with isPresent(), which returns true if a value is present. However, ifPresent() is often preferred, as it executes a provided lambda expression only if the value exists.

java

Main

copy
123456789101112131415161718
package com.example; import java.util.Optional; public class Main { public static void main(String[] args) { Optional<String> productOpt = Optional.ofNullable(null); if (productOpt.isPresent()) { System.out.println("Product found: " + productOpt.get()); } else { System.out.println("Product not found."); } // A more concise approach productOpt.ifPresent(product -> System.out.println("Product: " + product)); } }

In the first example, you manually check for a value using isPresent() before calling get(). The second example removes the need for an if statement by using a lambda expression that runs only if the product is present.

Providing a Default Value

Sometimes, when a value is missing, returning an alternative is a good idea. This can be done with orElse(), which provides a fallback value. If generating the fallback requires computation, orElseGet() is more efficient, as it only executes the function when necessary.

java

Main

copy
123456789101112131415
package com.example; import java.util.Optional; public class Main { public static void main(String[] args) { Optional<String> productOpt = Optional.ofNullable(null); String product = productOpt.orElse("Default product"); System.out.println("Selected product: " + product); String productLazy = productOpt.orElseGet(() -> "Fallback product"); System.out.println("Selected product (lazy): " + productLazy); } }

The difference is that orElse() always creates the fallback value, even if it's not needed, while orElseGet() calls the provided function only if Optional is empty.

Throwing an Exception If Value Is Missing

In some cases, the absence of a value is an error. In such situations, orElseThrow() can be used to throw an exception.

java

Main

copy
123456789101112
package com.example; import java.util.Optional; public class Main { public static void main(String[] args) { Optional<String> productOpt = Optional.ofNullable(null); String product = productOpt.orElseThrow(() -> new RuntimeException("Product not found")); System.out.println("Product: " + product); } }

Here, if the Optional is empty, the program throws a RuntimeException. This is useful when a missing value represents a critical error.

Transforming Values

Often, an Optional holds complex objects, but you may only need to work with specific fields. In such cases, you use map(), which applies a given function if a value is present.

java

Main

copy
123456789101112
package com.example; import java.util.Optional; public class Main { public static void main(String[] args) { Optional<String> productOpt = Optional.ofNullable("Laptop"); Optional<Integer> nameLengthOpt = productOpt.map(String::length); nameLengthOpt.ifPresent(length -> System.out.println("Product name length: " + length)); } }

If the Optional is empty, map() simply returns Optional.empty(). Otherwise, it applies String::length and returns an Optional<Integer>.

Filtering Values

Sometimes, you need to keep a value only if it meets a certain condition. The filter() method helps by retaining the value if the given predicate returns true or returning Optional.empty() if the condition is not met.

java

Main

copy
123456789101112
package com.example; import java.util.Optional; public class Main { public static void main(String[] args) { Optional<String> productOpt = Optional.of("Laptop"); Optional<String> filteredProductOpt = productOpt.filter(name -> name.length() > 5); filteredProductOpt.ifPresent(name -> System.out.println("Filtered product: " + name)); } }

If the string's length is greater than 5, the value is retained; otherwise, the Optional becomes empty.

1. What happens if you call get() on an empty Optional?

2. What will this code print?

3. What will be the result of the following code?

4. Which method is best for providing a default value that is only computed when needed?

question mark

What happens if you call get() on an empty Optional?

Select the correct answer

question mark

What will this code print?

Select the correct answer

question mark

What will be the result of the following code?

Select the correct answer

question mark

Which method is best for providing a default value that is only computed when needed?

Select the correct answer

Everything was clear?

How can we improve it?

Thanks for your feedback!

Section 3. Chapter 5
We're sorry to hear that something went wrong. What happened?
some-alt