Introduction
Java 8 introduced the Optional class and the Stream API, both of which are powerful tools for handling collections and potentially null values in a more robust and expressive manner. When dealing with lists, you may encounter scenarios where filtering based on certain conditions is necessary, and those conditions might involve handling null values. Combining the Stream API with Optional allows you to filter lists more elegantly, ensuring that null values are handled properly without causing NullPointerException.
In this guide, we’ll explore how to filter a list using Optional in Java 8, covering different scenarios where this technique can be applied.
Table of Contents
- Problem Statement
- Solution Steps
- Java Program
- Example 1: Filtering a List of Non-Null Values Using Optional
- Example 2: Filtering a List Based on an Optional Condition
- Example 3: Filtering a List of Custom Objects with an Optional Attribute
 
- Example 1: Filtering a List of Non-Null Values Using 
- Conclusion
Problem Statement
When working with lists, you may need to filter out elements based on certain conditions, including the presence or absence of null values. The goal is to use Optional in Java 8 to filter lists more effectively, ensuring that null values are handled gracefully.
Example:
- Problem: Filtering a list where some elements might be nullor some attributes of objects might benull.
- Goal: Use Optionalto filter the list in a clean and effective way, avoidingNullPointerException.
Solution Steps
- Use Optionalto Handle PotentiallynullValues: Wrap elements inOptionalto avoidNullPointerException.
- Filter Lists Based on Optional Conditions: Use Optionalin conjunction with the Stream API to filter lists based on conditions that may involvenullvalues.
- Handle Custom Objects with Optional Attributes: Apply filtering logic to lists of custom objects where certain attributes might be null.
Java Program
Example 1: Filtering a List of Non-Null Values Using Optional
This example demonstrates how to filter out null values from a list using Optional.
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
/**
 * Java 8 - Filter a List Using Optional
 * Author: https://www.rameshfadatare.com/
 */
public class OptionalFilterExample1 {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("John", null, "Ramesh", "Alice", null, "Bob");
        // Filter the list to remove null values using Optional
        List<String> filteredNames = names.stream()
            .map(Optional::ofNullable)  // Wrap elements in Optional
            .filter(Optional::isPresent)  // Keep only present values
            .map(Optional::get)  // Unwrap the values
            .collect(Collectors.toList());
        System.out.println("Filtered Names: " + filteredNames);
    }
}
Output
Filtered Names: [John, Ramesh, Alice, Bob]
Explanation
- Optional.ofNullable(): Wraps each element in an- Optional, handling- nullvalues gracefully.
- filter(Optional::isPresent): Filters out- Optionalobjects that are empty, effectively removing- nullvalues from the list.
- map(Optional::get): Unwraps the values from the- Optionalobjects, restoring the original type.
Example 2: Filtering a List Based on an Optional Condition
In this example, we filter a list based on a condition that might or might not be present.
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
/**
 * Java 8 - Filter a List Using Optional
 * Author: https://www.rameshfadatare.com/
 */
public class OptionalFilterExample2 {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(5, 10, 15, 20, 25, 30);
        Optional<Integer> filterThreshold = Optional.of(15);
        // Filter the list based on the optional condition
        List<Integer> filteredNumbers = numbers.stream()
            .filter(n -> filterThreshold.map(threshold -> n > threshold).orElse(true))
            .collect(Collectors.toList());
        System.out.println("Filtered Numbers: " + filteredNumbers);
    }
}
Output
Filtered Numbers: [20, 25, 30]
Explanation
- filterThreshold.map(): Applies the filtering condition only if the- Optionalcontains a value.
- orElse(true): If the- Optionalis empty, all elements are included in the result.
Example 3: Filtering a List of Custom Objects with an Optional Attribute
This example demonstrates filtering a list of custom objects based on an optional attribute.
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
/**
 * Java 8 - Filter a List Using Optional
 * Author: https://www.rameshfadatare.com/
 */
public class OptionalFilterExample3 {
    public static void main(String[] args) {
        List<User> users = Arrays.asList(
            new User("John", Optional.of("New York")),
            new User("Ramesh", Optional.empty()),
            new User("Alice", Optional.of("Los Angeles")),
            new User("Bob", Optional.empty())
        );
        // Filter users based on the presence of a city
        List<User> usersWithCity = users.stream()
            .filter(user -> user.getCity().isPresent())
            .collect(Collectors.toList());
        System.out.println("Users with City: " + usersWithCity);
    }
}
class User {
    private String name;
    private Optional<String> city;
    public User(String name, Optional<String> city) {
        this.name = name;
        this.city = city;
    }
    public Optional<String> getCity() {
        return city;
    }
    @Override
    public String toString() {
        return name + " (" + city.orElse("No City") + ")";
    }
}
Output
Users with City: [John (New York), Alice (Los Angeles)]
Explanation
- filter(user -> user.getCity().isPresent()): Filters the list to include only users who have a non-empty- Optionalcity attribute.
- Optional<String>: The- cityattribute is wrapped in an- Optional, indicating that it might be absent.
Conclusion
Using Optional in Java 8 to filter a list is a powerful way to handle potentially null values and conditional logic more elegantly. By leveraging Optional.ofNullable(), Optional.map(), and Optional.isPresent(), you can write cleaner and more robust code that effectively manages the presence or absence of values. Whether you’re working with simple lists or complex objects with optional attributes, this approach ensures that your filtering logic is both safe and expressive.