1

I was following this Question and was trying to get a new way of concatenating two arrays.

int[] c = {1, 34};
int[] d = {3, 1, 5};

I came up with this:

 Integer [] res= Stream.of(c, d)
                .flatMap(Stream::of)
                .toArray(Integer[]::new);

Above compiles fine but i get this exception:

Exception in thread "main" java.lang.ArrayStoreException
    at java.lang.System.arraycopy(Native Method)
    at java.util.stream.SpinedBuffer.copyInto(SpinedBuffer.java:194)
    at java.util.stream.Nodes$SpinedNodeBuilder.copyInto(Nodes.java:1290)
    at java.util.stream.SpinedBuffer.asArray(SpinedBuffer.java:215)
    at java.util.stream.Nodes$SpinedNodeBuilder.asArray(Nodes.java:1296)
    at java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:439)

What is my mistake, and please give a explanation so that i can understand the concept.

PS: I have seen Dealing with an ArrayStoreException and believe that my question consists of stream which are incompitable types that is why they are not getting stored, so two questions are different.

Community
  • 1
  • 1
Vishwa Ratna
  • 5,567
  • 5
  • 33
  • 55
  • Your arrays are primitive arrays (`int[]`) while you want to concatenate them to a wrapper class array (`Integer[]::new`) - I'd say autoboxing doesn't work here. – Thomas Feb 26 '19 at 08:21
  • I think you just misunderstood the explanation, as you have just answered your own question. – Ivan Kukic Feb 26 '19 at 08:26

3 Answers3

4

Stream.of treats the input array as a single element. Use Arrays.stream() instead.

int[] c = {1, 34};
int[] d = {3, 1, 5};

int[] res= Stream.of(c, d)
  .flatMapToInt(Arrays::stream)
  .toArray();

  for (int re : res) {
      System.out.println(re);
  }

Result:

1
34
3
1
5

If you want to have it boxed, go for:

Integer[] res= Stream.of(c, d)
  .flatMapToInt(Arrays::stream).boxed()
  .toArray(Integer[]::new);
Grzegorz Piwowarek
  • 13,172
  • 8
  • 62
  • 93
  • when i do `Arrays.stream()` in Intellij compiler , then compiler gives me hint that `Arrays.stream()` can be written as `Stream.of()` , so whats make the difference? – Vishwa Ratna Feb 26 '19 at 08:27
  • @CommonMan are you trying my example? there are two signatures of Stream.of and compiler can infer the wrong one if it's put in a different context – Grzegorz Piwowarek Feb 26 '19 at 08:28
  • what is the significance of `flatMapToInt(Arrays::stream)` , will it not just return array stream? – Vishwa Ratna Feb 26 '19 at 08:29
  • sir i am trying your example. – Vishwa Ratna Feb 26 '19 at 08:30
  • then I'd consider it a bug... but it doesn't happen in my IDEA 2018.3.4 – Grzegorz Piwowarek Feb 26 '19 at 08:33
  • 1
    if I replace it manually with Stream.of, it doesn't compile - I'd trust javac on this one – Grzegorz Piwowarek Feb 26 '19 at 08:34
  • understood, need more practice, till now i got what you all said. – Vishwa Ratna Feb 26 '19 at 08:35
  • 2
    Even if it worked, replacing the idiomatic `Arrays.stream` to *stream* over an *array* with the `Stream.of` method which just happens to accept an array due to the way, *varargs* have been implemented in Java, is a really poor advice. That trick would work if you used `IntStream.of`, for the same reasons `Stream.of` works with arrays of objects, still, there is no reason to replace `Arrays.stream`. – Holger Feb 26 '19 at 10:25
3
Stream.of(c, d)

is a Stream<int[]>. You can't store int[] elements in an Integer[].

Use IntStream.concat instead:

IntStream.concat(IntStream.of(c), IntStream.of(d)).boxed()
   .toArray(Integer[]::new);
Andy Turner
  • 137,514
  • 11
  • 162
  • 243
  • I saw many answers in https://stackoverflow.com/questions/54864223/concatenating-two-int but i wanna do something different, so i tried, please suggest how can i build upon my approach? – Vishwa Ratna Feb 26 '19 at 08:22
3

.flatMap(Stream::of) on a Stream<int[]> returns a Stream<int[]> (Since Stream.of(int[]) will execute Stream<T> of(T t) and not Stream<T> of(T... values)). Therefore these elements cannot be stored in an Integer[] array.

You can work with IntStreams instead:

int [] res= Stream.of(c, d)
                  .flatMapToInt (IntStream::of)
                  .toArray();
Eran
  • 387,369
  • 54
  • 702
  • 768