为什么 Collections.shuffle() 对于我的数组失败?
为什么我的代码不起作用?
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。
我期待一个随机打乱的序列。
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.
I was expecting a randomly shuffled sequence.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
Arrays.asList()
不能像您期望的那样应用于原始类型的数组。当应用于int[]
时,Arrays.asList()
会生成int[]
列表,而不是Integer< 列表/代码>s。因此,您对新创建的
int[]
列表进行洗牌。这是 Java 中可变参数和泛型的微妙行为。
Arrays.asList()
被声明为因此,它可以采用某种类型
T
的多个参数并生成包含这些参数的列表,或者它可以采用T
类型的一个参数code>T[] 并返回由该数组支持的列表(这就是可变参数的工作原理)。但是,后一个选项仅当
T
是引用类型(即不是诸如int
之类的基本类型)时才有效,因为只有引用类型可以用作泛型中的类型参数(T
是一个类型参数)。因此,如果您传递
int[]
,则会得到T
=int[]
,并且您的代码无法按预期工作。但是,如果您传递引用类型的数组(例如,Integer[]
),您将得到T
=Integer
并且一切正常:Arrays.asList()
can't be applied to arrays of primitive type as you expect. When applied toint[]
,Arrays.asList()
produces a list ofint[]
s instead of list ofInteger
s. Therefore you shuffle a newly created list ofint[]
.This is a subtle behaviour of variadic arguments and generics in Java.
Arrays.asList()
is declared asSo, it can take several arguments of some type
T
and produce a list containing these arguments, or it can take one argument of typeT[]
and return a list backed by this array (that's how variadic arguments work).However, the latter option works only when
T
is a reference type (i.e. not a primitive type such asint
), because only reference types may be used as type parameters in generics (andT
is a type parameter).So, if you pass
int[]
, you getT
=int[]
, and you code doesn't work as expected. But if you pass array of reference type (for example,Integer[]
), you getT
=Integer
and everything works:尝试将这行代码添加到您的测试中:
您将看到正在打印单个元素
List
。在原始数组上使用
Arrays.asList
会导致asList
将int[]
视为单个对象而不是数组。它返回List
而不是List
。因此,您基本上是在对单个元素List
进行洗牌,因此没有任何内容真正被洗牌。请注意,已经给出的一些答案是错误的,因为
asList
返回由原始数组支持的列表,没有任何内容被复制 - 所有更改都反映在原始数组中。Try adding this line of code to your test:
You will see you are printing out a single element
List
.Using
Arrays.asList
on a primitive array causeasList
to treat theint[]
as a single object rather than an array. It returns aList<int[]>
instead of aList<Integer>
. So, you are basically shuffling a single elementList
and so nothing really gets shuffled.Notice that some of the answers already given are wrong because
asList
returns a List backed by the original array, nothing gets copied - all changes are reflected in the orginal array.这是行不通的,因为对
shuffle
的调用是在Arrays.asList
返回的List
上操作的,而不是在底层数组上操作的。因此,当您迭代数组以打印出值时,没有任何变化。您想要做的是保存对Arrays.asList
返回的List
的引用,然后打印出该List
的值(而不是比数组的值)在随机播放
之后。That doesn't work because the call to
shuffle
is operating on theList
returned byArrays.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 theList
returned byArrays.asList
, and then print out the values of thatList
(rather than the values of the array) after youshuffle
it.存储 Arrays.asList 返回的列表并随机播放......
Store the list resturned by Arrays.asList and shuffle that...