Keywords: Java 8 | Streams API | HashMap Filtering
Abstract: This article explores the use of Java 8 Streams API for filtering and collecting values from a HashMap. Through practical examples, it details how to filter Map entries based on key conditions and handle both single-value and multi-value collection scenarios. The discussion covers the application of entrySet().stream(), filter and map operations, and the selection of terminal operations like findFirst and Collectors.toList, providing developers with comprehensive solutions and best practices.
Introduction
In Java 8, the Streams API introduced significant enhancements for collection operations, particularly when working with key-value pairs in structures like HashMap. This article demonstrates how to use Streams to filter a HashMap and collect corresponding values through a concrete example.
Problem Scenario
Consider a HashMap<Integer, List<String>> where keys are integers and values are lists of strings. For instance:
Map<Integer, List<String>> id1 = new HashMap<>();
List<String> list1 = new ArrayList<>();
list1.add("r1");
list1.add("r4");
List<String> list2 = new ArrayList<>();
list2.add("r2");
list2.add("r5");
List<String> list3 = new ArrayList<>();
list3.add("r3");
list3.add("r6");
id1.put(1, list1);
id1.put(2, list2);
id1.put(3, list3);
id1.put(10, list2);
id1.put(15, list3);
Single Value Collection: Exact Key Match
To filter and retrieve a single list based on a specific key (e.g., key 1), use the following approach:
Optional<List<String>> result = id1.entrySet()
.stream()
.filter(e -> e.getKey() == 1)
.map(Map.Entry::getValue)
.findFirst();
Here, entrySet().stream() converts the Map to a Stream, filter retains entries with key 1, map extracts the value, and findFirst returns an Optional of the first match. Although HashMap does not guarantee order, this method is safe and effective for single-key matches.
Multi-Value Collection: Pattern-Based Key Matching
For collecting multiple lists based on a key pattern (e.g., keys ending with 1), employ:
List<List<String>> results = id1.entrySet()
.stream()
.filter(e -> e.getKey() % 10 == 1) // e.g., keys 1, 10, 15
.map(Map.Entry::getValue)
.collect(Collectors.toList());
This code applies a condition via filter, extracts values with map, and collects all matching values into a list using Collectors.toList().
Technical Analysis
Streams operations are divided into intermediate (e.g., filter, map) and terminal (e.g., findFirst, collect) operations. In single-value scenarios, findFirst returns an Optional to avoid null pointer exceptions; in multi-value cases, Collectors.toList ensures type safety. Note that the original code uses raw types like List; it is advisable to use generics such as List<String> for better code quality.
Conclusion
Java 8 Streams offer powerful and flexible tools for filtering and collecting values from HashMaps. By appropriately selecting intermediate and terminal operations, developers can efficiently handle both single and multi-value collections, enhancing code readability and maintainability.