Trying to convert array of ints to a list - java

I'm trying to convert an array of type int to a List by doing
List<Integer> endingRoutesBusStopsList = Arrays.asList(endingRoutesBusStops);
but for some reason I keep getting an error saying
Type mismatch: cannot convert from List<int[]> to List<Integer>
I don't understand what the issue is.
I know doing
List<int[]> endingRoutesBusStopsList = Arrays.asList(endingRoutesBusStops);
will solve the error, but then I can't use it the way I want.
Anyone have any ideas?

This is caused by the fact that int[] is different from Integer[]. Autoboxing does not work on Arrays.

The issue is because an "int[]" is an Object,
Arrays.asList(T...) gets generic vararg, that it means it treats "int[]" as "Object" (the common superclass for array int[] and Integer is Object)
so that from asList method perspective you don't pass an array of ints, but you pass an object .
In any way you should make implicit convertion from int to wrapper Integer. It is advisable to make it explicitly.

We are missing some more of your code, but in general, let me try and answer with code:
This works:
Integer[] arrayOfInt = { Integer.valueOf(0), Integer.valueOf(1) };
List<Integer> listOfInt = Arrays.asList(arrayOfInt);
This works too because the primitive "1" is autoboxed to an Integer object:
Integer[] arrayOfInt = { 1, 2, 3, 4 };
List<Integer> listOfInt = Arrays.asList(arrayOfInt);
Finally, this won't work because an int[] cannot be autoboxed to Integer[]:
int[] arrayOfInt = { 1, 2, 3, 4 };
List<Integer> listOfInt = Arrays.asList(arrayOfInt);
UPDATE: this comes from way down in the comments in a discussion with #MichaelBorek . This example repeatedly tries the same code either autoboxing or not. The cost of autoboxing seems to be that the code that uses it takes 5 times longer than the one that uses Objects directly.

Related

Java array initialization second variable type

int[] myArray = new int[5];
Hey guys,
I know there are other ways to initialize an array like:
int[] myArray = {1,2,3,4,5};
But can you tell me what the second int in the top example stands for?
I think the first "int" already specifies the array to have integer values, doesn't it?
The construct in int[] myArray = { 1, 2, 3, 4, 5 }; is handled as a special case. The compiler knows that { 1, 2, 3, 4, 5 } is creating an int[] array because of the declared type.
However, the full array creation syntax for the int array is new int[5] (it can vary), which tells the compiler that a new int[] array is created, regardless of the declared type:
For example, you can declare an Object variable, and assign an int array to it:
Object myArrayObject = new int[5]; //OK: this creates an int array
Whereas this won't work:
Object myArrayObject = { 1, 2, 3, 4, 5 }; //won't compile
With int and other primitive types, you're correct, the double declaration is largely superfluous.
But consider this example:
Object [] array = new String[5];
This is valid Java code (even though it is slightly broken*).
On a more general level it follows the same pattern as when you're initialising any variable with a new object:
Foo foo = new Foo();
The first Foo is the type of the variable (what shape the box is), the second is the type of the actual object (what shape is the thing you put in the box).
Note: Starting with Java 10, you can declare local variables with the keyword var, thus eliminating the need to specify the type twice:
var array = new int[5];
The compiler will infer from this that the type of array will be the same as the object it's initialised with. (int[] in this case).
*It is broken because if you try to put into the array anything other than a String, the code only fails at runtime, not during compilation.
So when you type new, you are specifying you want java to allocate memory to the heap. How much memory? Ah yes enough memory for 5 integers, int[5]. So java will allocated enough consecutive memory on the heap to store 5 integers.
int[] myArray = new int[5];
means you declare an array that can contain integer values called myArray (by int[] myArray) and you define it as an integer-array of size 5 afterwards (= new int[5];);
These steps are made inline, you could alternatively do the same in two lines:
int[] myArray; // declaration
myArray = new int[5]; // definition
First is the data type of the array. And other int is for the intialization of 5 integer object in the array

java : Understanding Arrays.asList(T...array) method for primitive types

I wrote following code and was surprised to see the output:
Integer a = 211;
int b = 211;
int[] array = {210,211,212};
System.out.println(Arrays.asList(array).contains(a));
System.out.println(Arrays.asList(array).contains(b));
Output:
false
false
I found this question and some other questions linked to it and learned that asList method doesn't Autobox stuffs. I checked the returned type in eclipse javadoc preview:
I couldn't quite understand this return type. int[] is an object and not a primitive so its fine. I'm sure that I'm not getting List<Integer> (something which I expected) but I'm not sure how to use the thing which is being returned. My questions are:
1. How exactly do I expect that list methods will work when I'm expecting an List of Integer and getting a List of int[] ?
2. In case of Strings the return type is List of String and not List of String[]. What sort of implementation differences are there?
3. What good is this method for primitives if things are so uncertain?
There are obviously 3 questions here so lets tackle them one by one:
How exactly do I expect that list methods will work when I'm expecting an List of Integer and getting a List of int[] ?
Well, List methods will work exactly as expected, a List<T> is a list of types T. Here T is an int[] so a List<int[]> will contains arrays as each element:
[{1, 2}, {3, 4}, {1, 6}]
So get(i) will return the ith element. In the case of Arrays.asList the List contains a single element, namely the int[] so:
int[] array = {210,211,212};
List<int[]> list = Arrays.asList(array);
Will be
[{210, 211, 212}]
And so
list.get(0)[0] == 210
In case of Strings the return type is List of String and not List of String[]. What sort of implementation differences are there?
String is an Object, not a primitive type. The difference follows from that.
What good is this method for primitives if things are so uncertain?
Things are not uncertain. This method results in defined and predictable behaviour. It's just not very useful for primitives. This is (yet another) side effect of combining Java's type system with generics.
Note with Java 8 the conversion of an int[] to a List<Integer> is very simple:
List<Integer> list = Arrays.stream(array).
boxed().
collect(toList());
You are not getting a Lit or a List (which can't be), you're getting a List of arrays of integer.
So your list does not contain 211, it contains an array that then contains 211.
The array is not "unrolled" into the list, it is added "as is" to a newly created list.
So :
System.out.println(Arrays.asList(array).contains(array)); // Will return true
System.out.println(Arrays.asList(a).contains(a)); // Will return true
It is because Arrays.asList() is a variadic generic function. Change this,
int[] array = {210,211,212};
to
Integer[] array = { 210, 211, 212 };
And the output will be true and true.
Arrays.asList takes objects as params. Since int[] is an object, you get the List.
If you want a list of integers you should do Arrays.asList(211,212,213).
int[] array = {210,211,212};
Arrays.asList(array)
is equal to
List<int[]> asList = Arrays.asList(array);
Change
int[] array = {210,211,212}; to Integer[] array = {210,211,212}; and it will work.
and its equals to List<Integer> asList = Arrays.asList(array);

Arrays.asList return type mismatch confusion [duplicate]

This question already has answers here:
Boxing with Arrays.asList()
(2 answers)
Closed 9 years ago.
Why does the following not return a list of integers?
int[] ints = new int[] { 1, 2, 3, 4, 5 };
List<Integer> intsList = Arrays.asList(ints); //compilation error
But instead a List of int[]
While this
String[] strings = new String[] { "Hello", "World" };
List<String> stringsList = Arrays.asList(strings);
Returns a list of String. I am guessing it fails due to it being an array of primitives but why? And how do I actually return a list of int.
It's because Arrays.asList(new int[] { 1, 2, 3, 4, 5 }) will create a List<int[]> with one item, not a List<Integer> with five items.
Note however that this would do what you expected:
List<Integer> intsList = Arrays.asList(1, 2, 3, 4, 5);
Your other alternatives are:
to create an Integer[] in the first place, or
to populate your list in a loop
The method is defined as:
public static <T> List<T> asList(T... a)
So in your first case, T is int[] and you are passing a single object to the method (i.e. the array), therefore it returns a list of int[].
I think you are mistaking with asList(1, 2, 3, 4, 5) (i.e. 5 items)
The T in List<T> must be some subtype of java.lang.Object, which int is not. THe only other interpretation is, as we are using ... that you are supplying an array of int[], i.e. an int[][]. So you get List<int[]>.
String is a subtype of Object, so this works as expected. Also the only way it can work prior to varargs introduction in J2SE 5.0. Generally the interpretation of existing code should not alter between language versions.
Now, if you wanted a List<Integer> you could go through and box each integer. If there a lot of these elements in your program then memory may be an issue. You may want to use a third-party library that compactly backs a List<Integer> with an int[], or just stick with arrays for primitives. It's unfortunate that Java does not support value types.

Why does Arrays.asList on an int[] return a List<int[]>, and not a List<int>?

Consider this code:
int[] tcc = {1,2,3};
ArrayList<Integer> tc = Arrays.asList(tcc);
For the above, Java complains that it cannot convert from List<int[]> to ArrayList<Integer>.
What's wrong with this?
Why is it List<int[]> and not List<int>?
An ArrayList can hold only objects not primitives such as ints, and since int != Integer you can't do what you're trying to do with an array of primitives, simple as that. This will work for an array of Integer though.
This will work:
ArrayList tc = new ArrayList(Arrays.asList(1,2,3));
You could have it as:
List<int[]> tc = Arrays.asList(tcc);
Arrays.asList returns a List, not an ArrayList. And since Arrays.asList is a varargs function, it thinks tcc is one element of a bigger array.
If you want to have just a List of Integers, you'd have to rewrite it as SB mentioned in the comments for Hovercraft Of Eel's answer:
List<Integer> tc = Arrays.asList(1, 2, 3);
Alternatively, if you make tcc an Integer[], you can still use your array as an argument in the following snippet by explicitly asking for a List of Integer, providing a type parameter that agrees with the passed array:
Integer[] tcc = {1,2,3};
List<Integer> tc = Arrays.<Integer>asList(tcc);

How to convert an int[] array to a List?

I expected this code to display true:
int[] array = {1, 2};
System.out.println(Arrays.asList(array).contains(1));
The method Arrays.asList(T ...) is, when generics are erased and varargs are transformed, actually equal to a method of type Arrays.ofList(Object[]) (which is the, binary equivalent, JDK 1.4 version of the same Method).
An array of primitives is an Object (see also this question), but not an Object[], so the compiler thinks you are using the varargs version and generates an Object array around your int array. You could illustrate what's happening by adding an extra step:
int[] array = {1, 2};
List<int[]> listOfArrays = Arrays.asList(array);
System.out.println(listOfArrays.contains(1));
This compiles and is equivalent to your code. It also obviously returns false.
The compiler translates varargs calls into calls with a single array, so calling a varargs method that expects parameters T ... with parameters T t1, T t2, T t3 is equivalent to calling it with new T[]{t1, t2, t3} but the special case here is that varargs with primitives will be autoboxed before the array is created if the method needs an object array. So the compiler thinks the int array is passed in as a single Object and creates a single element array of type Object[], which it passes to asList().
So here's the above code once again, the way the compiler implements it internally:
int[] array = {1, 2};
// no generics because of type erasure
List listOfArrays = Arrays.asList(new Object[]{array});
System.out.println(listOfArrays.contains(1));
Here are some good and bad ways to call Arrays.asList() with int values:
// These versions use autoboxing (which is potentially evil),
// but they are simple and readable
// ints are boxed to Integers, then wrapped in an Object[]
List<Integer> good1 = Arrays.asList(1,2,3);
// here we create an Integer[] array, and fill it with boxed ints
List<Integer> good2 = Arrays.asList(new Integer[]{1,2,3});
// These versions don't use autoboxing,
// but they are very verbose and not at all readable:
// this is awful, don't use Integer constructors
List<Integer> ugly1 = Arrays.asList(
new Integer(1),new Integer(2),new Integer(3)
);
// this is slightly better (it uses the cached pool of Integers),
// but it's still much too verbose
List<Integer> ugly2 = Arrays.asList(
Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(3)
);
// And these versions produce compile errors:
// compile error, type is List<int[]>
List<Integer> bad1 = Arrays.asList(new int[]{1,2,3});
// compile error, type is List<Object>
List<Integer> bad2 = Arrays.asList(new Object[]{1,2,3});
Reference:
Java Tutorial > Classes and Objects > Passing Information to a Method or a Constructor > Varargs
Arrays.asList(T ...)
But to actually solve your problem in a simple way:
There are some library solutions in Apache Commons / Lang (see Bozho's answer) and in Google Guava:
Ints.contains(int[], int) checks whether an array of ints contains a given int
Ints.asList(int ...) creates a List of Integers from an int array
The Arrays.asList(array) will result in a singleton list of an int[].
It works as you expect if you change int[] to Integer[]. Don't know if that helps you though.
Arrays.asList(ArrayUtils.toObjectArray(array))
(ArrayUtils is from commons-lang)
But if you want to just call contains there is no need of that. Simply use Arrays.binarySearch(..) (sort the array first)
This
System.out.println(Arrays.asList(array).contains(array));
returns true.
It seems like your understanding of Arrays.asList(T... a) is wrong. You wouldn't be the first person to make an assumption as to how it works.
Try it with
System.out.println(Arrays.asList(1, 2).contains(1));
Autoboxing just doesn't work the way you want it to in this case. The following code may be a bit verbose, but does the job of converting an int array to a list:
List<Integer> list = new ArrayList<Integer>(array.length);
for (int value : array) {
list.add(value);
}
The following code displays true:
Integer[] array = {1, 2};
System.out.println(Arrays.asList(array).contains(1));
(Your version fails, since Int's not beeing objects, but Int[] is an object. Therefor you will call asList(T... a) with one element beeing a Collection, since it is not possible to have an Collection a.)
When you call
Arrays.asList(array)
on your array of primitives, you get a List instance containing one object: an array of int values! You have to first convert the array of primitives into an array of objects, as #Bozho suggests in his answer.
If you only want to check whether the array contains certain element just iterate over array and search for element. This will take o(n/2). All other solutions are less effective. Any method that copies array to list must iterate over array and therefore this operation only requires n atomic assignments.
I dont think there is a method call you could use. Try it like this
List<Integer> list = new ArrayList<Integer>();
for (int index = 0; index < array.length; index++)
{
list.add(array[index]);
}

Categories

Resources