4

I am trying to generate a int[][] using Java 8 streams.

This is what I have done so far:

objects.parallelStream()
            .map(o -> o.getPropertyOnes()
                    .parallelStream()
                    .map(t-> t.getIndex())  //<-- getIndex() returns int
                    .mapToInt(i -> i)
                    .toArray())            //<-- here I have a Stream<int[]>
            .toArray();                   //lost here

At the end of outer.map() I have a Stream<int[]>, but not sure how to convert that to int[][]. Please suggest.

6
  • are you looking for flatMap? Commented Nov 30, 2016 at 13:55
  • @Eugene No, don't want to flatten the collection, rather want to create a 2d int array. Commented Nov 30, 2016 at 13:57
  • how would you convert a Stream<int[]> to int[][]? Can you provide and example? Even better show us your input and the desired output, it's unclear what you are trying to do Commented Nov 30, 2016 at 14:00
  • 5
    You have to use toArray(int[][]::new). Commented Nov 30, 2016 at 14:02
  • 3
    Instead of the two step .map(t -> t.getIndex()) .mapToInt(i -> i), you can use straight-forwardly mapToInt(t -> t.getIndex()). Commented Nov 30, 2016 at 15:29

3 Answers 3

7

First you can simplify the map().mapToInt() to mapToInt(t-> t.getIndex()) (maybe you should use a method reference like <type>::getIndex).

As you said you have Stream<int[]> after the map stage. Then you only need to provide an array generator function like:

int[][] array = Stream.of(1, 2, 3, 4)
                      .map(i -> IntStream.range(0, i).toArray())
                      .toArray(int[][]::new);

Output:

[[0], [0, 1], [0, 1, 2], [0, 1, 2, 3]]
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for the answer. I still need to wait couple of minutes to accept it. One question though, I tried to do toArray(int[]::new) for the inner map, i.e. instead of .map(t-> t.getIndex()).mapToInt(i -> i).toArray(), tried this: .map(t-> t.getIndex()).toArray(int[]::new), but it didn't work. Any idea why?
@SayanPal Well you have a Stream<Integer> this cannot be stored int an int[]. Stream::mapToInt returns an IntStream which provides a toArray method which returns an int[]. This is exactly what you need.
3

You need a toArray(generator) method that helps us to specify a return type by an IntFunction<T[]> function:

int[][] a = Stream.of(new int[]{1, 2, 3}, new int[]{4, 5, 6}).toArray(int[][]::new);

instead of toArray(), which returns Object[] regardless of an incoming type in a Stream (invokes toArray(Object[]::new) internally):

Object[] a = Stream.of(new int[]{1, 2, 3}, new int[]{4, 5, 6}).toArray();

If you are interested in, behind the scenes, all of this have the following look:

  1. forming a Node [an ArrayNode in our case] (an immutable container for keeping an ordered sequence of elements) from a Pipeline of the previous stage;
  2. array size calculation by using the node size (node.count());
  3. getting a new empty array with a needed length by our IntFunction<T[]> generator (i -> new int[i][] or simply int[][]::new);
  4. copying from the node to this array and returning the latter.

Comments

1

If you want to generate 2D array of sequential number of n X n where n in the degree.

int n = 4;
System.out.println(Arrays.deepToString(IntStream.rangeClosed(0, n - 1)
        .boxed().map(x -> IntStream.rangeClosed(x * n + 1, (x + 1) * n)
            .boxed().toArray()).toArray()));

Output: [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.