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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3981420/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 07:52:42  来源:igfitidea点击:

Why does Collections.shuffle() fail for my array?

javashufflerandom-access

提问by Dmitry

Why does my code not work?

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

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

The result is: 0 1 2 3 4 5 6 7 8 9.

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

I was expecting a randomly shuffled sequence.

我期待一个随机洗牌的序列

采纳答案by axtavt

Arrays.asList()can't be applied to arrays of primitive type as you expect. When applied to int[], Arrays.asList()produces a list of int[]s instead of list of Integers. Therefore you shuffle a newly created list of int[].

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

This is a subtle behaviour of variadic arguments and generics in Java. Arrays.asList()is declared as

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

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

So, it can take several arguments of some type Tand produce a list containing these arguments, or it can take one argument of type T[]and return a list backed by this array (that's how variadic arguments work).

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

However, the latter option works only when Tis a reference type (i.e. not a primitive type such as int), because only reference types may be used as type parameters in generics (and Tis a type parameter).

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

So, if you pass int[], you get T= int[], and you code doesn't work as expected. But if you pass array of reference type (for example, Integer[]), you get T= Integerand everything works:

因此,如果您通过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] + " "); 
} 

回答by Nate W.

That doesn't work because the call to shuffleis operating on the Listreturned by Arrays.asList, not on the underlying array. Thus, when you iterate over the array to print out the values, nothing has changed. What you want to do is save a reference to the Listreturned by Arrays.asList, and then print out the values of that List(rather than the values of the array) after you shuffleit.

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

回答by mmccomb

Store the list resturned by Arrays.asList and shuffle that...

存储由 Arrays.asList 返回的列表并洗牌...

List myShuffledList = Arrays.asList(arr);
Collections.shuffle(myShuffledList);

回答by MAK

Try adding this line of code to your test:

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

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

You will see you are printing out a single element List.

您将看到您正在打印单个元素List

Using Arrays.asListon a primitive array cause asListto treat the int[]as a single object rather than an array. It returns a List<int[]>instead of a List<Integer>. So, you are basically shuffling a single element Listand so nothing really gets shuffled.

使用Arrays.asList上基本数组原因asList治疗int[]作为单个对象,而不是阵列。它返回 aList<int[]>而不是 a List<Integer>。所以,你基本上List是在打乱单个元素,所以没有真正被打乱。

Notice that some of the answers already given are wrong because asListreturns a List backed by the original array, nothing gets copied - all changes are reflected in the orginal array.

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