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

问题描述 投票:22回答:4

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

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] + " ");
        }
    }
}

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

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

java shuffle random-access
4个回答
44
投票

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

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

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

因此,它可以采用某些类型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] + " "); 
} 

6
投票

尝试在测试中添加以下代码:

List l=Arrays.asList(arr);
System.out.println(l);

你会看到你打印出单个元素List

在原始数组上使用Arrays.asList会导致asListint[]视为单个对象而不是数组。它返回一个List<int[]>而不是List<Integer>。所以,你基本上是在改变单个元素List,所以没有什么能真正被洗牌。

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


-2
投票

这不起作用,因为对shuffle的调用是在List返回的Arrays.asList上运行,而不是在底层阵列上运行。因此,当您遍历数组以打印出值时,没有任何更改。你想要做的是保存对List返回的Arrays.asList的引用,然后在你List之后打印出shuffle的值(而不是数组的值)。


-3
投票

存储由Arrays.asList重新存储的列表并随机播放......

List myShuffledList = Arrays.asList(arr);
Collections.shuffle(myShuffledList);
© www.soinside.com 2019 - 2024. All rights reserved.