8

I have the following Java code:

import java.util.Arrays;
import java.util.Collections;

public class Test {
    public static void main(String[] args) {
        int[] test = {1,2,3,4,5};
        Collections.rotate(Arrays.asList(test), -1);
        for(int i = 0; i < test.length; i++) { System.out.println(test[i]); }
    }

}

I want the array to be rotated, but the output I get is

1
2
3
4
5

Why is this?

And is there an alternative solution?

EDIT:

So this works:

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Test {
    public static void main(String[] args) {
        int[] test = {1,2,3,4,5};
        List<Integer> testList = new ArrayList<Integer>();
        for(int i = 0; i < test.length; i++) { testList.add(test[i]); }
        Collections.rotate(testList, -1);
        for(int i = 0; i < test.length; i++) { System.out.println(testList.get(i)); }
    }

}

But Arrays.asList is supposed to return a list that when written to, copies the changes to the array. Is there any way to fix this without manually doing the conversion from array to list?

I (think that I) can't afford to waste that much CPU time and memory to do the conversion.

1 Answer 1

20

This is a tricky problem: yes, asList backs the List it returns with the array, and changes to the List will "write-through" to the array. However, due to how varargs of T... interacts with an array of primitive type in this case, you're actually creating a list with 1 element!

    int[] test = {1,2,3,4,5};
    System.out.println(Arrays.asList(test).size());
    // prints "1"

Let's try something different:

    int[] test = {1,2,3,4,5};
    List<Integer> list = Arrays.asList(test);
    // "Type mismatch: cannot convert from List<int[]> to List<Integer>"

As you see, the varargs with an int[] doesn't work the way you intended, and the compiler gives an error. Arrays.asList actually returns a 1-element List<int[]> instead of a 5-element List<Integer>.

Using Integer[] instead of int[] works as expected:

    Integer[] test = {1,2,3,4,5};
    Collections.rotate(Arrays.asList(test), -1);
    System.out.println(Arrays.toString(test));
    // prints "[2, 3, 4, 5, 1]"

More explanation

The full signature of asList is <T> List<T> Arrays.asList(T... a). Note that T can't be int in this case, for the same reason why you can't have a List<int> in Java: T needs to be a reference type.

Consider the following snippet:

    System.out.println(Arrays.asList(1,2,3));
    // prints "[1, 2, 3]"

What happens here is that each int is boxed into an Integer, and the varargs mechanism "works" and asList creates a list of 3 elements. Now consider the following form instead:

    System.out.println(Arrays.asList(new int[] { 1,2,3 }));
    // prints "[[I@xxxxxx]"

Now the argument to asList is an int[]. T can't be an int, therefore, the T... varargs mechanism "fails", and asList only gets one element, and it's an int[], instead of the int values themselves.

Now consider this form:

    System.out.println(Arrays.asList(new Integer[] { 1,2,3 }));
    // prints "[1, 2, 3]"

Now since Integer[] is a T..., asList gets 3 elements as expected.

See also

Sign up to request clarification or add additional context in comments.

2 Comments

See also TS-1188 2006 JavaOne Conference, Java Puzzlers presentation Puzzle 7. "Fib O'Nacci"
asList() is allowing 'test' because it is also a reference type, as arrays are Objects. So when you say, Arrays.asList(test) the 'array of integers' is kept in List and is returned.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.