19

The following code in Java return -1. I thought that it should return 3.

int[] array = {1,2,3,4,5,6}; 
System.out.println(Arrays.asList(array).indexOf(4));

Can you help me understand how this function works.

Thanks

Karthik
  • 4,950
  • 6
  • 35
  • 65
Somdutta
  • 193
  • 1
  • 2
  • 9
  • 1
    `Arrays.asList` does not work for primitive arrays. It gives a `List` containing the original `int[]`. -1 means that 4 is not one of the `List` items – Paul Boddington Jul 31 '15 at 00:27
  • `Arrays.asList(int[])` is creating a `List` of one element which contains the whole `int[]` array. Change `int[]` to `Integer[]` instead – MadProgrammer Jul 31 '15 at 00:30
  • Trying writing the generic type of `asList` explicitly (`Arrays.asList(array)`) rather than relying on type inference, and the compiler will tell you why that doesn't work. – Chris Martin Jul 31 '15 at 01:10
  • [Guava](https://github.com/google/guava)'s [`Ints.asList()`](http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/primitives/Ints.html#asList(int...)) addresses this problem; [more info](https://code.google.com/p/guava-libraries/wiki/PrimitivesExplained). – dimo414 Jul 31 '15 at 03:31

8 Answers8

13

Before Java 5, Arrays.asList used to accept an Object[]. When generics and varargs were introduced into the language this was changed to

public static <T> List<T> asList(T... arr)

In your example, T cannot be int because int is a primitive type. Unfortunately, the signature matches with T equal to int[] instead, which is a reference type. The result is that you end up with a List containing an array, not a List of integers.

In Java 4, your code would not have compiled because an int[] is not an Object[]. Not compiling is preferable to producing a strange result, and in Effective Java, Josh Bloch says retrofitting asList to be a varargs method was a mistake.

Paul Boddington
  • 37,127
  • 10
  • 65
  • 116
9

Arrays.asList expect an object (or more). Your array (array) is a sole object, thus calling the method will create a list of only one object, which is your array.

Calling indexOf on your list will return -1 because 4 will never be found as your list contains the array object, not the list of datas that your array contains.

Jean-François Savard
  • 20,626
  • 7
  • 49
  • 76
5
int[] array = {1,2,3,4,5,6};
Arrays.stream(array).boxed().collect(Collectors.toList()).indexOf(4);

should do what you want while keeping the original int[].

You get an IntStream of it, box it into a Stream<Integer>, collect it to a List<Integer> and then can do an .indexOf() search.

glglgl
  • 89,107
  • 13
  • 149
  • 217
  • 2
    You might want to use an `IntStream` instead of storing the all array into a list for calling `indexOf` - `OptionalInt index = IntStream.range(0, array.length).filter(i -> array[i] == 4).findFirst();` – Alexis C. Jul 31 '15 at 09:51
4

You've got answers as as to what is happening to your array when you use Arrays.asList().

Other things to consider:

  • Since your array is sorted, consider Arrays.binarySearch()
  • If your array is not sorted, a simple custom indexOf method can perform the same without wasting cycles converting the int[] to a List<Integer>

Example:

public static void main(String[] args) throws Exception {
    int[] array = {1, 2, 3, 4, 5, 6};
    System.out.print("Binary Search: ");
    System.out.println(Arrays.binarySearch(array, 4));

    int[] array2 = {5, 8, 2, 5, 3, 4, 1};
    System.out.print("Manual Search: ");
    System.out.println(indexOf(array2, 4));
}

public static int indexOf(int[] array, int search) {
    for (int i = 0; i < array.length; i++) {
        if (array[i] == search) {
            return i;
        }
    }
    return -1;
}

Results:

Binary Search: 3
Manual Search: 5
Shar1er80
  • 9,001
  • 2
  • 20
  • 29
3

Since you are using an array of primitive type, this will not work. The array is of type int. Were you using Integer type for example, that will work. -1 means the index of the specified element was not found.

This is what you want to do:

Integer[] array = {1,2,3,4,5,6};
System.out.println(Arrays.asList(array).indexOf(4));
Ralph
  • 2,959
  • 9
  • 26
  • 49
3

You cannot use primitive types such as int as parameters to generic classes in Java since int is not a class,you shoud use Integer instead :

Integer[] array = {1,2,3,3,4,5}; 

List Arraylist=Arrays.asList(array);
System.out.println(Arraylist.indexOf(1));
System.out.println(Arraylist.indexOf(4));

output:

0
4

note that Arraylist.indexOf(i) return the index of first occurrence of the element i in list :

System.out.println(Arraylist.indexOf(3));

it will return 2 which is first occurrence of element 3 , not 3 since there is 2 elements of 3 in list.

Oghli
  • 2,200
  • 1
  • 15
  • 37
2

Because when you do this with a primary data type array, it will be treated as the first element in the List.

int[] array = {1,2,3,4,5,6};
System.out.println(Arrays.asList(array));

You will get this:

[[I@474e8d67]
Sean Zhang
  • 108
  • 6
2
int[] array = {1,2,3,4,5,6};
  • In java array is considered as an Object
  • int[] is particularly Object and not Object[]
  • To call Arrays.asList you need zero or more Objects

Your method gets called in this way,

Arrays.asList((Object)(array));//Yes
Arrays.asList(1,2,3,4,5,6);//No

So you will have List<int[]> and not List<Integer>

Now, you might have asked your self that if Arrays.asList(1,2,3,4) works than why not Arrays.asList(arrayInt) ?

In Arrays.asList(1,2,3,4) all the values are autoboxed in to the Integer which is solely an Object so in above case Integer[] cad do the trick.

akash
  • 22,664
  • 11
  • 59
  • 87