SurenNihalani
SurenNihalani

Reputation: 1438

Stream from two dimensional array in java

I am trying to get an IntStream out of an n dimensional int arrays. Is there a nice API way to do it? I know the concatenate method for two streams.

Upvotes: 41

Views: 51504

Answers (4)

fiftyone_51
fiftyone_51

Reputation: 125

Adding to the previous answers, the method Arrays::stream returns a sequential stream (see: Oracle Javadoc). In some situations, a parallel stream might improve performance. To explicitly request a parallel stream, you first need to convert to a List via Arrays::asList, then call parallelStream() on the resulting List.

To calculate the sum of a two dimensional int array using a IntStream, you can use following code:

int[][] twoDimArray = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };
IntStream intStream = Arrays.asList(twoDimArray)
    .parallelStream()               // "rows" in parallel
    .flatMapToInt(Arrays::stream);  // "columns" sequentially
int sum = intStream.sum();          // = 45

The Stream created for processing the outer layer (rows, first dimension) is now executing in parallel, while the Streams for the inner layer (columns, second dimension) are still sequential (using Arrays::stream mentioned above).

Depending on the size and structure of your array, you might see a performance increase by factor 4 (that's what I measured in my own tests) or none at all. If your calculations are time critical, it might be worth a try to use a parallel Stream.

Upvotes: 2

Alex K.
Alex K.

Reputation: 153

To process the elements only, use flatMap as in Rohit's answer.

To process the elements with their indices, you may use IntStream.range as follows.

import java.util.stream.IntStream;
import static java.util.stream.IntStream.range;

public class StackOverflowTest {
    public static void main(String... args) {
        int[][] arr = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
        // Map the two dimensional array with indices.
        final IntStream intStream = range(0, arr.length).flatMap(row -> range(0, arr[row].length).map(col -> {
            final int element = arr[row][col];
            // E.g. multiply elements in odd numbered rows and columns by two.
            return row % 2 == 1 || col % 2 == 1 ? element * 2 : element;
        }));
        // Prints "1 4 3 8 10 12 7 16 9 ".
        intStream.forEachOrdered(n -> System.out.print(n + " "));
    }
}

Upvotes: 2

Jacob G.
Jacob G.

Reputation: 29680

To further expand on Rohit's answer, a method reference can be used to slightly shorten the amount of code required:

int[][] arr = { {1, 2, 3}, 
                {4, 5, 6},
                {7, 8, 9} };

IntStream stream = Arrays.stream(arr).flatMapToInt(Arrays::stream);

Upvotes: 18

Rohit Jain
Rohit Jain

Reputation: 213253

Assuming you want to process array of array sequentially in row-major approach, this should work:

int[][] arr = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };
IntStream stream = Arrays.stream(arr).flatMapToInt(x -> Arrays.stream(x));

First it invokes the Arrays.stream(T[]) method, where T is inferred as int[], to get a Stream<int[]>, and then Stream#flatMapToInt() method maps each int[] element to an IntStream using Arrays.stream(int[]) method.

Upvotes: 55

Related Questions