tshepang
tshepang

Reputation: 12459

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));

Upvotes: 21

Views: 12023

Answers (12)

Donald Raab
Donald Raab

Reputation: 6686

If you're open to using a third-party library, the following options are possible using Eclipse Collections. Both primitive IntList and boxed List<Integer> can be used to solve the problem depending on what you require. The lists can also either be mutable or immutable, again based on your requirements.

@Test
public void intArrayToList()
{
    int[] array = {1, 2};

    // Creates an Eclipse Collections MutableIntList from the int[]
    MutableIntList mutableIntList = IntLists.mutable.with(array);

    // Creates an Eclipse Collections ImmutableIntList from the int[]
    ImmutableIntList immutableIntList = IntLists.immutable.with(array);

    IntList expectedIntList = IntLists.immutable.with(1, 2);
    Assertions.assertTrue(mutableIntList.contains(1));
    Assertions.assertEquals(expectedIntList, mutableIntList);
    Assertions.assertTrue(immutableIntList.contains(1));
    Assertions.assertEquals(expectedIntList, immutableIntList);

    // Converts the MutableIntList to a MutableList<Integer>
    // Boxes the int values as Integer objects
    MutableList<Integer> mutableList = mutableIntList.collect(i -> i);

    // Converts the ImmutableIntList to an ImmutableList<Integer>
    // Boxes the int values as Integer objects
    ImmutableList<Integer> immutableList = immutableIntList.collect(i -> i);

    List<Integer> expectedList = List.of(1, 2);
    Assertions.assertTrue(mutableList.contains(1));
    Assertions.assertEquals(expectedList, mutableList);
    Assertions.assertTrue(immutableList.contains(1));
    Assertions.assertEquals(expectedList, immutableList);
}

MutableIntList and ImmutableIntList will hold onto a primitive int[] so there will be no boxing of int values to Integer. MutableList<Integer> and ImmutableList<Integer> will hold onto boxed Integer values.

Note: I am a committer for Eclipse Collections.

Upvotes: 0

Oleksandr Pyrohov
Oleksandr Pyrohov

Reputation: 16216

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

Direct answer using modern Java features:

int[] array = {1, 2};
List<Integer> list = IntStream.of(array).boxed().toList();
System.out.println(list.contains(1)); // true

Note: toList() is available since Java 16.

An alternative since Java 8 would be collect(Collectors.toList()).

Upvotes: 2

Sean Patrick Floyd
Sean Patrick Floyd

Reputation: 298838

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:


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:

Upvotes: 37

HaskellElephant
HaskellElephant

Reputation: 9891

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.)

Upvotes: 1

AlexR
AlexR

Reputation: 115328

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.

Upvotes: 0

dogbane
dogbane

Reputation: 274562

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);
}

Upvotes: 1

Qwerky
Qwerky

Reputation: 18435

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));

Upvotes: 1

Bozho
Bozho

Reputation: 597076

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)

Upvotes: 5

Pointy
Pointy

Reputation: 413720

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.

Upvotes: 0

Boris Pavlović
Boris Pavlović

Reputation: 64632

This

System.out.println(Arrays.asList(array).contains(array));

returns true.

Upvotes: 1

aioobe
aioobe

Reputation: 420951

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.

Upvotes: 15

Jinesh Parekh
Jinesh Parekh

Reputation: 2141

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]);
  }

Upvotes: -1

Related Questions