Java 8 – Filter a Map by Value Using Lambda

Introduction

Java 8 introduced lambda expressions and the Stream API, enabling developers to manipulate collections and maps in a more concise and functional way. Filtering a map by its values is a common task that can be efficiently handled using lambda expressions. Whether you’re dealing with simple types like String or Integer, or more complex custom objects, lambda expressions can simplify the filtering process.

In this guide, we’ll explore how to filter a map by its values using lambda expressions in Java 8. We will cover both simple examples and examples involving custom objects.

Table of Contents

  • Problem Statement
  • Solution Steps
  • Java Program
    • Filtering a Map with Simple Types
    • Filtering a Map with Custom Objects
  • Advanced Considerations
  • Conclusion

Problem Statement

The task is to create a Java program that:

  • Filters a map based on specific conditions applied to the map’s values using a lambda expression.
  • Returns a new map containing only the entries that satisfy the condition.

Example:

  1. Simple Example: Filter a map of integers to keep only those with values greater than 10.
  2. Custom Objects Example: Filter a map of Product objects to keep only those with a price greater than $500.

Solution Steps

  1. Create a Simple Map: Define a map with simple types like Integer or String.
  2. Create a Map of Product Objects: Define a map with product IDs as keys and Product objects as values.
  3. Use the filter() Method: Utilize the Stream API to filter the map based on values using a lambda expression.
  4. Collect the Results: Use Collectors.toMap() to collect the filtered results back into a map.

Java Program

Filtering a Map with Simple Types

Let’s start with a simple example where we filter a map of integers based on their values.

import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

public class FilterSimpleMapByValue {

    public static void main(String[] args) {
        // Step 1: Create a simple Map with integer values
        Map<String, Integer> numberMap = new HashMap<>();
        numberMap.put("One", 1);
        numberMap.put("Two", 2);
        numberMap.put("Ten", 10);
        numberMap.put("Twenty", 20);
        numberMap.put("Thirty", 30);

        // Step 2: Filter the map by value using a lambda expression
        // Example: Keep only entries where the value is greater than 10
        Map<String, Integer> filteredMap = numberMap.entrySet()
            .stream()
            .filter(entry -> entry.getValue() > 10)
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

        // Step 3: Display the filtered map
        filteredMap.forEach((key, value) -> 
            System.out.println("Key: " + key + ", Value: " + value));
    }
}

Output

Key: Twenty, Value: 20
Key: Thirty, Value: 30

Explanation

  • Filtering by Value: filter(entry -> entry.getValue() > 10) filters the entries in the map based on the condition that the value must be greater than 10.
  • Collecting Results: The filtered entries are collected back into a map using Collectors.toMap().

Filtering a Map with Custom Objects

Now, let’s consider a more complex example where we filter a map of custom Product objects.

import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

class Product {
    private String name;
    private double price;

    public Product(String name, double price) {
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public double getPrice() {
        return price;
    }

    @Override
    public String toString() {
        return name + " ($" + price + ")";
    }
}

public class FilterCustomMapByValue {

    public static void main(String[] args) {
        // Step 1: Create a Map of Product objects with product IDs as keys
        Map<Integer, Product> productMap = new HashMap<>();
        productMap.put(1, new Product("Laptop", 1200.00));
        productMap.put(2, new Product("Smartphone", 800.00));
        productMap.put(3, new Product("Tablet", 300.00));
        productMap.put(4, new Product("Smartwatch", 150.00));
        productMap.put(5, new Product("Headphones", 100.00));

        // Step 2: Filter the map by value using a lambda expression
        // Example: Keep only products with a price greater than $500
        Map<Integer, Product> filteredMap = productMap.entrySet()
            .stream()
            .filter(entry -> entry.getValue().getPrice() > 500)
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

        // Step 3: Display the filtered map
        filteredMap.forEach((key, product) -> 
            System.out.println("Product ID: " + key + ", Product: " + product));
    }
}

Output

Product ID: 1, Product: Laptop ($1200.0)
Product ID: 2, Product: Smartphone ($800.0)

Explanation

  • Product Class: The Product class has two attributes, name and price, along with getter methods and a toString() method for easy display.
  • Filtering by Value: The lambda expression filter(entry -> entry.getValue().getPrice() > 500) filters the entries in the map to keep only those products with a price greater than $500.
  • Collecting Results: The filtered entries are collected back into a map using Collectors.toMap().

Advanced Considerations

  • Complex Conditions: You can apply more complex filtering conditions by extending the lambda expression. For instance, you might filter products by both price and name.

  • Null Handling: Ensure to handle potential null values in the map to avoid NullPointerException. You can add a null check in the lambda expression if necessary.

  • Immutable Results: If you need the filtered map to be immutable, consider wrapping the result in Collections.unmodifiableMap().

Conclusion

This guide demonstrates how to filter a map by its values using lambda expressions in Java 8. We covered both simple examples and more complex examples involving custom objects like Product. Using lambda expressions with the Stream API allows for concise and efficient filtering of maps, making your code easier to read and maintain. Whether you’re working with primitive types or custom objects, this approach can be adapted to a wide range of filtering scenarios.

Leave a Comment

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

Scroll to Top