Java中使用数组的Collections.rotate()方法无法正常工作

8
我有以下Java代码:
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]); }
    }

}

我希望将数组旋转,但是我得到的输出是

1
2
3
4
5

为什么会这样呢?

是否有其他解决方案?

编辑:

所以这个方法可行:

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

}

但是Arrays.asList应该返回一个列表,当写入时,会将更改复制到数组中。有没有办法在不手动从数组转换为列表的情况下修复此问题?
我(认为我)无法承受浪费那么多 CPU 时间和内存来执行转换。
1个回答

20
这是一个棘手的问题:是的,asList 返回的 List 使用数组支持,并且对 List 的更改将“写入”数组。然而,由于 varargs 的 T... 与本例中原始类型的数组交互的方式,实际上你正在创建一个只有1个元素的列表!
    int[] test = {1,2,3,4,5};
    System.out.println(Arrays.asList(test).size());
    // prints "1"

让我们尝试一些不同的东西:

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

正如您所看到的,使用 int[] 的可变参数不按您预期的方式工作,编译器会报错。实际上,Arrays.asList 返回一个包含1个元素的 List<int[]> 而不是包含5个元素的 List<Integer>

使用 Integer[] 而不是 int[] 则按预期工作:

    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]"

更多解释

asList 的完整签名是 <T> List<T> Arrays.asList(T... a)。需要注意的是,在这种情况下,T 不能是 int,原因与为什么你不能在 Java 中有一个 List<int> 相同: T 需要是引用类型。

考虑以下代码片段:

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

这里发生的事情是每个int都被装箱为一个Integer,然后可变参数机制“起作用”,asList创建了一个由3个元素组成的列表。现在考虑下面的形式:
    System.out.println(Arrays.asList(new int[] { 1,2,3 }));
    // prints "[[I@xxxxxx]"

现在asList的参数是一个int[]。由于T不能是int,因此T...可变参数机制“失败了”,asList只得到一个元素,它是一个int[],而不是int值本身。

现在考虑以下形式:

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

现在由于Integer[]是一个T...asList按预期得到了3个元素。

另请参阅


1
另请参阅 TS-1188 2006 JavaOne 大会,Java Puzzlers 演示文稿第七个谜题“Fib O'Nacci”。 - polygenelubricants
asList() 允许 'test',因为它也是一个引用类型,就像数组是对象一样。因此,当你说 Arrays.asList(test) 时,'整数数组' 被保留在 List 中并返回。 - jai

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接