Question

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.

Was it helpful?

Solution

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[].

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

OTHER TIPS

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);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top