11

In this question it has already been answered that both expressions are equal, but in this case they produce different results. For a given int[] scores, why does this work:

Arrays.stream(scores)
        .forEach(System.out::println);

...but this does not:

Arrays.asList(scores).stream()
        .forEach(System.out::println);

As far as I know .stream() can be called on any Collection, which Lists definitely are. The second code snippet just returns a stream containing the array as a whole instead of the elements.

AdHominem
  • 1,204
  • 3
  • 13
  • 32

3 Answers3

17

The behavior you see is not specific to Streams. Arrays.asList(scores) returns a List<int[]> when you pass to it an int[], since a generic type parameter can't be replaced by a primitive type. Therefore, when you call asList(T... a), the compiler uses int[] in place of T.

If you change scores to Integer[], you'll get the output you expect (i.e. Arrays.asList(scores) will return a List<Integer>).

Eran
  • 387,369
  • 54
  • 702
  • 768
  • I see. It's just strange because I remember me doing stuff like that in the past and it worked. Would it have worked if I had declared the List in advance like this: `List scoresAsList = new ArrayList<>(scores);`? – AdHominem May 16 '16 at 11:32
  • 4
    @AdHominem That wouldn't work, since you can't pass an array to an `ArrayList` constructor. You can only pass a Collection. – Eran May 16 '16 at 11:36
  • As a side note, `Stream.of(scores).forEach(System.out::println);` does the same as `Arrays.asList(scores).stream().forEach(System.out::println);`… – Holger Jun 15 '16 at 12:39
9

The reason the second code snippet does not work is that there is no such thing as List<int> in Java. That is why Arrays.asList(scores) does not produce what you expect.

Switching from int[] to Integer[] would fix this problem, in the sense that the two pieces of code would produce identical results. However, your code would be less efficient, because all ints would be boxed.

In fact, efficiency is the reason behind having overloads of stream for primitive arrays. Your call Arrays.stream(scores) is routed to stream(int[] array), producing IntStream object. Now you can apply .forEach(System.out::println), which calls println(int), again avoiding boxing.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • 1
    Pray for Project Valhalla then :D – java8.being May 16 '16 at 11:21
  • @java8.being: since writing a wrapper `List` for an `int[]` is roughly ten lines of code, and for streaming, `Arrays.stream(scores)` already works, I don’t see the point of praying for something for which we don’t even know what and how it will change about this issue… – Holger May 17 '16 at 12:06
  • @Holger I meant for this line: `The reason the second code snippet does not work is that there is no such thing as List in Java.` – java8.being May 17 '16 at 12:16
  • @java8.being: If Project Valhalla manages to change that, there will be no real difference between a `List` and a `List<@NonNull Integer>` and `Arrays.asList` will continue to do what it does today, for compatibility reasons… – Holger May 17 '16 at 12:28
1

Arrays.asList expects arrays of Object not arrays of primitives. It does not complain on compile time because arrays of primitive is an object.

It can take one object as list but what is inside that object(arrays of primitive is an object) cannot be convert to list.

Arrays of primitive can be convert to stream using IntStream,DoubleStream and LongStream

like this

double[] doubleArray = {1.1,1.2,1.3};

DoubleStream.of(doubleArray).forEach(System.out::println);


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

IntStream.of(intArray).forEach(System.out::println);


long[] longArray = {1L,2L,3L};

LongStream.of(longArray).forEach(System.out::println);
Noor Nawaz
  • 2,175
  • 27
  • 36