Flattening Nested Collections in Java
Flattening nested collections is a common Java programming technique, particularly when dealing with large data structures. It entails transforming nested collections, such as lists of lists or maps of lists, into a single-level hierarchy. Processing is facilitated and data manipulation is made simpler as a result.
Understanding Flattening
In Java, flattening a nested collection entails combining multiple levels of collections into a single one. For example, given an array with numerous arrays as elements, flattening would yield a single array having all of the elements from the nested arrays.
Consider the following example:
Input: array= {{1, 2, 3, 4}, {5, 6, 7}, {8, 9}};
Processing: Flattening
Output: array={1, 2, 3, 4, 5, 6, 7, 8, 9};
The scenarios below demonstrate how to use the flatMap() method to flatten nested collections like maps, lists, and arrays in Java, resulting in a single-level structure that is easier to work with and process.
Example 1: Flattening a Collection of Lists
FileName: FlatteningExample.java
import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; public class FlatteningExample { // Method to flatten a collection of lists using flatMap() public staticList flatten(Collection > nestedLists) { return nestedLists.stream() .flatMap(List::stream) // flattening the nested lists .collect(Collectors.toList()); // collecting the flattened elements into a list } // Main method public static void main(String[] args) { // Example nested collection: list of lists of integers List
> nestedList = new ArrayList<>(); nestedList.add(Arrays.asList(1, 2, 3)); nestedList.add(Arrays.asList(4, 5)); nestedList.add(Arrays.asList(6, 7, 8)); // Flatten the nested collection List
flattenedList = flatten(nestedList); // Print the flattened list System.out.println("Flattened List: " + flattenedList); } }
Output:
Flattened List: [1, 2, 3, 4, 5, 6, 7, 8]
Explanation: The Java code utilizes the flatMap() method from Java Streams to flatten a nested collection of lists, merging all inner lists into a single flattened list.
Example 2: Flatten a Map Containing a List of Items as Values
FileName: FlattenMapOfLists.java
import java.util.*; import java.util.stream.Collectors; public class FlattenMapOfLists { // Method to flatten the values of a map of lists of lists public staticList flattenMapValues(Map>> map) { return map.values().stream() .flatMap(List::stream) .flatMap(List::stream) .collect(Collectors.toList()); } public static void main(String[] args) { // Create a map of integer keys to lists of lists of strings Map >> map = new HashMap<>(); map.put(1, Arrays.asList( Arrays.asList("Mr. Smith", "Mrs. Johnson"), Arrays.asList("Dr. Williams", "Professor Brown", "Sir Davis") )); // Flatten the values of the map and print the result List flattenedList = flattenMapValues(map); System.out.println(flattenedList); } }
Output:
[Mr. Smith, Mrs. Johnson, Dr. Williams, Professor Brown, Sir Davis]
Explanation: The code takes a Map where each value is a list of items. It flattens these lists into a single list using Java Streams. The flatMap() method is used to transform each list into a stream of its elements, which are then collected into a single list.
Example 3: Flatten a Stream of Two Lists of the Same Type
FileName: FlattenTwoLists.java
import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; public class FlattenTwoLists { public static void main(String[] args) { // Define two lists of lists List> list1 = Arrays.asList( Arrays.asList("Mr. Smith", "Mrs. Johnson"), Arrays.asList("Dr. Williams", "Professor Brown") ); List
> list2 = Arrays.asList( Arrays.asList("Sir Davis"), Arrays.asList("Mrs. Brown") ); // Flatten the nested lists within list1 and list2 into a single list List
flattenedList = Stream.concat(list1.stream(), list2.stream()) .flatMap(List::stream) .collect(Collectors.toList()); // Print the flattened list System.out.println(flattenedList); } }
Output:
[Mr. Smith, Mrs. Johnson, Dr. Williams, Professor Brown, Sir Davis, Mrs. Brown]
Explanation: Here, two lists of strings are combined into a single list using the flatMap() method. The Stream.of() method creates a stream of the two lists, which are then flattened into a single stream of elements and collected into a list.
Example 4: Flatten a List of Arrays of Strings
FileName: FlattenListOfArrays.java
import java.util.*; import java.util.stream.Collectors; public class FlattenListOfArrays { public static void main(String[] args) { // Define a list of arrays ListlistOfArrays = Arrays.asList( new String[]{"Mr. Smith", "Mrs. Johnson"}, new String[]{"Dr. Williams", "Professor Brown", "Sir Davis"}, new String[]{"Ms. Taylor", "Miss Clark"} ); // Flatten the list of arrays and collect into a single list List flattenedList = listOfArrays.stream() .flatMap(Arrays::stream) .collect(Collectors.toList()); // Print the flattened list System.out.println(flattenedList); } }
Output:
[Mr. Smith, Mrs. Johnson, Dr. Williams, Professor Brown, Sir Davis, Ms. Taylor, Miss Clark]
Explanation: Each array is transformed into a stream of its elements using flatMap(), and these streams are then combined into a single stream of strings and collected into a list.
Example 5: Flatten a Map of Sets of Characters
FileName: FlattenMapOfSets.java
import java.util.*;
import java.util.stream.Collectors;
public class FlattenMapOfSets {
public static void main(String[] args) {
// Define a map of sets of sets
Map
mapOfSets.put(1, new HashSet<>(Arrays.asList(
new HashSet<>(Arrays.asList('a', 'b')),
new HashSet<>(Arrays.asList('c', 'd'))
)));
mapOfSets.put(2, new HashSet<>(Arrays.asList(
new HashSet<>(Arrays.asList('e', 'f')),
new HashSet<>(Arrays.asList('g', 'h', 'i'))
)));
// Flatten the nested sets within the sets in mapOfSets into a single set
Set
.flatMap(Set::stream)
.flatMap(Set::stream)
.collect(Collectors.toSet());
// Print the flattened set
System.out.println(flattenedSet);
}
}
Output:
[a, b, c, d, e, f, g, h, i]
Explanation: The code defines a map called mapOfSets, where integer keys are associated with sets of characters. It then flattens the nested sets within the map's values into a single set of characters. Finally, it prints the flattened set.