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:
- Simple Example: Filter a map of integers to keep only those with values greater than 10.
- Custom Objects Example: Filter a map of
Productobjects to keep only those with a price greater than $500.
Solution Steps
- Create a Simple Map: Define a map with simple types like
IntegerorString. - Create a Map of
ProductObjects: Define a map with product IDs as keys andProductobjects as values. - Use the
filter()Method: Utilize theStreamAPI to filter the map based on values using a lambda expression. - 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
Productclass has two attributes,nameandprice, along with getter methods and atoString()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
nullvalues in the map to avoidNullPointerException. 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.