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.

Real-World Analogy: The Dresser Drawers

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:

  1. 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.
  2. Sorting (The Sorted step): Now that all the toys lie on the same flat surface, you line them up sequentially.
The act of pouring the nested contents out onto a single flat table is exactly what flatMap does in software.

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) or Arrays.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 single IntStream.
  • 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: flatMapToInt merges these arrays into a continuous primitive IntStream: [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 forEach loop 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.