Why does Collections.shuffle() fail for my array?
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 =开发者_如何学Go 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.
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 Integer
s. Therefore you shuffle a newly created list of int[]
.
This is a subtle behaviour of variadic arguments and generics in Java. Arrays.asList()
is declared as
public static <T> List<T> asList(T... a)
So, it can take several arguments of some type T
and 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).
However, the latter option works only when T
is 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 T
is a type parameter).
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
= Integer
and everything works:
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] + " ");
}
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
.
Using Arrays.asList
on a primitive array cause asList
to 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 List
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.
That doesn't work because the call to shuffle
is operating on the List
returned 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 List
returned by Arrays.asList
, and then print out the values of that List
(rather than the values of the array) after you shuffle
it.
Store the list resturned by Arrays.asList and shuffle that...
List myShuffledList = Arrays.asList(arr);
Collections.shuffle(myShuffledList);
精彩评论