Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

printing 2D array using IntStream's flatMap method

Tags:

java

java-8

I have a 2D array that I want to print using IntStream.

this is the array,

int[][] twoD = { { 1, 2 }, { 3, 4 }, { 5, 6 } };

Now, using nested loop this can be done like,

    for (int i = 0; i < twoD.length; i++) {
        for (int j = 0; j < twoD[i].length; j++) {
            System.out.println(twoD[i][j]);
        }
    }

but i want to use IntStream. and I recently learned about its flatMap method which I can use to achieve that, so I tried this,

    IntStream.range(0, twoD.length)
            .flatMap(j -> IntStream.range(0, twoD[j].length))
            .forEach(System.out::print);

and it outputs 010101.

One reason for the output being 010101 is that 010101 are index values not the values in the array and I have to map these values to the array values using something like, i -> twoD[i]

so I tried this,

    IntStream.range(0, twoD.length)
            .map(i -> twoD[i])
            .flatMap(j -> IntStream.range(0, twoD[j].length))
            .forEach(System.out::print);

but it gives error on map(i -> twoD[i]),

Type mismatch: cannot convert from int[] to int

but if it was 1D array then it would have worked, for example,

int[] oneD = { 1, 2, 3, 4, 5, 6 };

IntStream.range(0, oneD.length)
.map(i -> oneD[i])
.forEach(System.out::print);

How can I print the 2D array using the above approach ?

like image 288
Joe Avatar asked Dec 25 '22 22:12

Joe


1 Answers

I think you overcomplicate things. You could just do it like this:

Stream.of(twoD).flatMapToInt(IntStream::of).forEach(System.out::println);

What it does is:

  • get a Stream<int[]> from the int[][] array
  • flatMap each int[] to an IntStream so that you get back an IntStream with all the elements of the 2D array
  • for each element, print it


What you want to do is achievable but not very readable. A formal translation of your nested loop would be:
IntStream.range(0, twoD.length)
         .forEach(i -> IntStream.range(0, twoD[i].length)
                                .forEach(j -> System.out.println(twoD[i][j])));

which produces the same output, but as you can see it's not very readable. Here you don't need to stream the indices so the first approach with flatMapToInt is the best.

Now why your solution doesn't compile?

It's because map on an IntStream expect a mapping function that gives you back an int but you give an int[]. You need to use mapToObj and then again flatMapToInt to get an IntStream and finally print the contents (this isn't the only solution though).

IntStream.range(0, twoD.length)
         .mapToObj(i -> twoD[i])
         .flatMapToInt(IntStream::of)
         .forEach(System.out::print);

Do you gain in readability? Not really, so I suggest to use the first approach which is clear and concise.

Note that the last solution could be also written as:

IntStream.range(0, twoD.length)
         .flatMap(i -> IntStream.of(twoD[i]))
         .forEach(System.out::print);

... but I still prefer the first approach ! :)

like image 73
Alexis C. Avatar answered Dec 28 '22 06:12

Alexis C.