为什么Collections.shuffle()为我的数组失败?

Dmi*_*try 22 java shuffle random-access

为什么我的代码不起作用?

package generatingInitialPopulation;

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

public class TestShuffle {
    public static void main(String[] args) {
        int[] arr = new int[10];

        for (int i = 0; i < arr.length; i++) {
            arr[i] = i;
        }

        Collections.shuffle(Arrays.asList(arr));

        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

其结果是:0 1 2 3 4 5 6 7 8 9.

我期待一个随机改组的序列.

axt*_*avt 45

Arrays.asList()不能像你期望的那样应用于基本类型的数组.应用于时int[],Arrays.asList()会生成一个int[]s列表而不是Integers 列表.因此,您将随机播放新创建的列表int[].

这是Java中可变参数和泛型的微妙行为.Arrays.asList()被宣布为

public static <T> List<T> asList(T... a)
Run Code Online (Sandbox Code Playgroud)

因此,它可以采用某种类型的几个参数T并生成包含这些参数的列表,或者它可以采用一个类型的参数T[]并返回由此数组支持的列表(这是可变参数的工作方式).

但是,后一个选项仅在T引用类型(即不是诸如原始类型int)时才起作用,因为只有引用类型可以用作泛型T中的类型参数(并且是类型参数).

所以,如果你通过int[],你得到T= int[],你的代码不能按预期工作.但是如果你传递引用类型的数组(例如,Integer[]),你得到T= Integer并且一切正常:

Integer[] arr = new Integer[10]; 

for (int i = 0; i < arr.length; i++) { 
    arr[i] = i; 
} 

Collections.shuffle(Arrays.asList(arr)); 

for (int i = 0; i < arr.length; i++) { 
    System.out.print(arr[i] + " "); 
} 
Run Code Online (Sandbox Code Playgroud)

  • 因为Arrays.asList()创建了一个由数组支持的新列表.它没有像其他人所说的那样复制数组.Arrays.asList()返回的列表的每次更改也会更改支持它的数组. (3认同)
  • T不能是原始类型,因此在某种意义上,它不应该为原始类型编译.但是,由于varargs,使用单个对象调用asList是有效的,并且它将把它视为大小为1的数组.因此,它将以一种令人困惑的方式编译和工作. (3认同)
  • @Dmitry:因为Java泛型不适用于原始类型。参见,Arrays.asList()返回List &lt;T&gt;,但是您不能在Java中声明List &lt;int&gt;。 (2认同)

MAK*_*MAK 6

尝试将这行代码添加到您的测试中:

List l=Arrays.asList(arr);
System.out.println(l);
Run Code Online (Sandbox Code Playgroud)

你会看到你打印出一个元素List.

使用Arrays.asList上基本数组原因asList治疗int[]作为单个对象,而不是阵列.它返回一个List<int[]>而不是一个List<Integer>.所以,你基本上是在改变单个元素List,所以没有什么能真正被洗牌.

请注意,已经给出的一些答案是错误的,因为asList返回由原始数组支持的List,没有任何内容被复制 - 所有更改都反映在原始数组中.