In software development, we often organize data in multi-dimensional arrays, such as matrices, grids, or spreadsheets. While this layout is excellent for spatial modeling, it introduces challenges when you need to perform global operations like sorting, filtering, searching, or mapping across all elements.
To process this data efficiently, we need a way to decompose the nested structure. In Java, flattening is the process of converting a multi-dimensional array into a single, continuous one-dimensional stream of elements. By flattening nested arrays using the Stream API's flatMap operations, we can perform functional pipelines seamlessly.
To understand flattening, think of a dresser containing three separate drawers (representing our 2D array). Each drawer holds various numbers of toys marked with numeric labels. If you want to sort all the toys from smallest to largest, doing it while they remain split across separate drawers is clumsy and slow.
Instead, you follow this two-step process:
- Dumping (The FlatMap step): You pull open every drawer and pour all their contents onto a single long table. The drawers are removed, leaving you with a single flat line of toys.
- Sorting (The Sorted step): Now that all the toys lie on the same flat surface, you line them up sequentially.
The Stream Strategy
To implement this in Java:
- We start with a 2D jagged array
int[][] arr(where different rows can have different lengths). - We create a stream of these arrays:
Stream.of(arr)orArrays.stream(arr). This produces a stream of references to individual integer arrays. - We apply
flatMapToInt(Arrays::stream). This maps each array reference into its own primitive stream of values, then flattens and concatenates them into a singleIntStream. - Finally, we call
.sorted()on this unified stream to sort all elements, and print or collect them.
Step-by-Step Scenario Walkthrough
Let's trace the stream execution step-by-step for a jagged array:
int[][] arr = {
{1, 2, 3},
{-2, 0, 5, 7},
{-3, 4, 6, 8, 9}
};
- Stream Generation:
Stream.of(arr)yields a stream containing three array references:[{1, 2, 3}, {-2, 0, 5, 7}, {-3, 4, 6, 8, 9}]. - Flattening:
flatMapToIntmerges these arrays into a continuous primitiveIntStream:[1, 2, 3, -2, 0, 5, 7, -3, 4, 6, 8, 9]. - Sorting: The
.sorted()method sorts the continuous stream in natural ascending order:[-3, -2, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]. - Printing: The
forEachloop prints each number sequentially to the console.
Java Implementation Code
Below is the complete Java code demonstrating 2D array flattening and sorting using Streams:
package io.practise.accolite;
import java.util.Arrays;
import java.util.stream.IntStream;
import java.util.stream.Stream;
public class FlatteningTwoDimentionalArray {
public static void main(String[] args) {
int[][] arr = {
{1, 2, 3},
{-2, 0, 5, 7},
{-3, 4, 6, 8, 9}
};
IntStream sorted = Stream.of(arr)
.flatMapToInt(Arrays::stream)
.sorted();
sorted.forEach(eachElement -> System.out.println(eachElement));
}
}
Conclusion & Complexity Analysis
Flattening a 2D array using flatMapToInt() is highly efficient, running in O(N) linear time for the flattening pass, followed by O(N log N) for sorting, where N is the total number of elements. By eliminating nested loops and temporary storage arrays, this approach makes processing jagged data structures elegant and highly readable.