Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Collections.rotate() with an array doesn't work

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.

like image 668
steve_72 Avatar asked May 08 '10 17:05

steve_72


People also ask

How does the collections rotate work?

Collections class. It is used to rotate the elements present in the specified list of Collection by a given distance. Syntax: public static void rotate(List< type > list, int distance) Parameters : list - the list to be rotated. distance - the distance to rotate the list.

How do you rotate a value in an array?

The array can be left rotated by shifting its elements to a position prior to them which can be accomplished by looping through the array and perform the operation arr[j] = arr[j+1]. The first element of the array will be added to the last of rotated array.


1 Answers

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

  • Java: Array of primitive data types does not autobox
    • An int[] does not autobox to an Integer[]
like image 59
polygenelubricants Avatar answered Oct 25 '22 21:10

polygenelubricants