Reputation: 1438
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
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
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
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
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