Arrays.asList() not working as it should?
Solution 1
How about this?
Integer[] ints = new Integer[] {1,2,3,4,5};
List<Integer> list = Arrays.asList(ints);
Solution 2
There's no such thing as a List<int>
in Java - generics don't support primitives.
Autoboxing only happens for a single element, not for arrays of primitives.
As for how to correct it - there are various libraries with oodles of methods for doing things like this. There's no way round this, and I don't think there's anything to make it easier within the JDK. Some will wrap a primitive array in a list of the wrapper type (so that boxing happens on access), others will iterate through the original array to create an independent copy, boxing as they go. Make sure you know which you're using.
(EDIT: I'd been assuming that the starting point of an int[]
was non-negotiable. If you can start with an Integer[]
then you're well away :)
Just for one example of a helper library, and to plug Guava a bit, there's com.google.common.primitive.Ints.asList
.
Solution 3
Because java arrays are objects and Arrays.asList()
treats your int array as a single argument in the varargs list.
Solution 4
Enter Java 8, and you can do following to collect in a boxed Array:
Integer[] boxedInts = IntStream.of(ints).boxed().toArray(Integer[]::new);
Or this to collect in a boxed List
List<Integer> boxedInts = IntStream.of(ints).boxed().collect(Collectors.toList());
However, this only works for int[]
, long[]
, and double[]
. This will not work for byte[]
.
Note that Arrays.stream(ints)
and IntStream.of(ints)
are equivalent. So earlier two examples can also be rewritten as:
Integer[] boxedIntArray = Arrays.stream(ints).boxed().toArray(Integer[]::new);
List<Integer> boxedIntList = Arrays.stream(ints).boxed().collect(Collectors.toList());
This last form could be favored as it omits a primitive specific subtype of Stream
. However, internally it is still a bunch of overloaded's which in this case still create a IntStream
internally.
Solution 5
The problem is not with Arrays.asList()
. The problem is that you expect autoboxing to work on an array - and it doesn't. In the first case, the compiler autoboxes the individual ints before it looks at what they're used for. In the second case, you first put them into an int array (no autoboxing necessary) and then pass that to Arrays.asList()
(not autoboxing possible).
Mohammad Taha
Android geek, TDD nut, International Speaker, ex Shazamer, currently the Principal Software Engineer for Apps at ASOS. Noti.st | Twitter | LinkedIn | GitHub
Updated on July 05, 2022Comments
-
Mohammad Taha almost 2 years
I have a float[] and i would like to get a list with the same elements. I could do the ugly thing of adding them one by one but i wanted to use the Arrays.asList method. There is a problem though. This works:
List<Integer> list = Arrays.asList(1,2,3,4,5);
But this does not.
int[] ints = new int[] {1,2,3,4,5}; List<Integer> list = Arrays.asList(ints);
The asList method accepts a varargs parameter which to the extends of my knowledge is a "shorthand" for an array.
Questions:
Why does the second piece of code returns a
List<int[]>
but notList<int>
.Is there a way to correct it?
Why doesn't autoboxing work here; i.e.
int[]
toInteger[]
?
-
palantus over 14 yearsBeat me, but it would be better with an explanation also.
-
Mohammad Taha over 14 yearsunbelievable... It works with reference but not with primitive types :D thanks a lot. :)
-
Mohammad Taha over 14 yearsHm but is there an easy way to convert an int[] to Integer[]? The thing is i get my array via a method call and i cannot change it.
-
whiskeysierra about 14 years@mmyers In fact, that's what this question is all about. +1 for ChssPly76
-
Jonik almost 14 years@Savvas: See stackoverflow.com/questions/880581/java-convert-int-to-integer or Jon Skeet's answer here. Libraries like Apache Commons Lang or Guava will be of some help.
-
Geek over 10 yearsWhy does "Autoboxing only happens for a single element, not for arrays of primitives.". What do you think is the reason for this design decision?
-
Jon Skeet over 10 years@Geek: Well what would you suggest as an alternative? It would be odd for a
double[]
to be automatically converted to aDouble[]
by copying all the elements - such that a cast of a reference type would effectively clone the data, unlike every other operation in Java. If you're suggesting that aDouble[]
should be able to be backed by adouble[]
in a "view" sort of way, that has other issues such as how you store null references and again the difference between this and other arrays. I think it was the right decision. -
marcinj about 10 yearswith java 8 you can use stream api: List<Integer> list = Arrays.stream(new int[]{1,2,3}).boxed().collect(Collectors.toList());, a bit verbose though
-
Maarten Bodewes over 9 yearsOne of these Guava functions that should have been added to Java a long way back. Horrible type juggling with primitive types is unfortunately not going away soon.
-
karl over 8 yearsWarning: lists returned by
Ints.asList
do not supportadd()
or related methods -
laertis about 6 yearsYou need to cast the result from
toArray()
since it returnsObject[]
-
laertis about 6 years
-
YoYo about 6 yearsOk. You are right. Type at that point is
Stream<Integer>
and notIntStream
. I have fixed it however by usingtoArray(Integer[]::new)
instead. Maybe simply typecasting here would be better? -
laertis about 6 yearsThis is actually a different overloaded
toArray()
implementation (docs.oracle.com/javase/8/docs/api/java/util/stream/…) that uses a generator function and does the job properly. It's better to avoid typecasting where you can.. -
user7294900 almost 5 yearsCan warning be overcome Type safety: The expression of type List needs unchecked conversion to conform to List<Integer> ?
-
Abdul almost 5 yearsArray.asList works only with Objects? Not Primitive array?