Java 8 – Filter a List Using Optional

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
  • 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 null or some attributes of objects might be null.
  • Goal: Use Optional to filter the list in a clean and effective way, avoiding NullPointerException.

Solution Steps

  1. Use Optional to Handle Potentially null Values: Wrap elements in Optional to avoid NullPointerException.
  2. Filter Lists Based on Optional Conditions: Use Optional in conjunction with the Stream API to filter lists based on conditions that may involve null values.
  3. 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 null values gracefully.
  • filter(Optional::isPresent): Filters out Optional objects that are empty, effectively removing null values from the list.
  • map(Optional::get): Unwraps the values from the Optional objects, 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 Optional contains a value.
  • orElse(true): If the Optional is 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 Optional city attribute.
  • Optional<String>: The city attribute 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.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top