Почему Collections.shuffle () не работает для моего массива? - PullRequest
22 голосов
/ 20 октября 2010

Почему мой код не работает?

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.

Я ожидал случайным образом перемешанной последовательности .

Ответы [ 4 ]

44 голосов
/ 20 октября 2010

Arrays.asList() нельзя применять к массивам примитивного типа, как вы ожидаете. При применении к int[], Arrays.asList() создает список int[] с вместо списка Integer с. Поэтому вы перетасовываете вновь созданный список 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 голосов
/ 20 октября 2010

Попробуйте добавить эту строку кода в свой тест:

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

Вы увидите, что вы печатаете один элемент List.

Используя Arrays.asList в примитивном массивезаставить asList рассматривать int[] как отдельный объект, а не как массив.Возвращает List<int[]> вместо List<Integer>.Итак, вы в основном тасуете один элемент List, и поэтому ничто на самом деле не тасуется.

Обратите внимание, что некоторые из ответов, которые уже даны, неверны, потому что asList возвращает список, поддерживаемый исходным массивом, ничего не получаетскопировано - все изменения отражаются в оригинальном массиве.

0 голосов
/ 20 октября 2010

Сохраните список, восстановленный Arrays.asList, и перемешайте его ...

List myShuffledList = Arrays.asList(arr);
Collections.shuffle(myShuffledList);
0 голосов
/ 20 октября 2010

Это не работает, потому что вызов shuffle работает на List, возвращаемом Arrays.asList, а не на базовом массиве. Таким образом, когда вы перебираете массив для вывода значений, ничего не меняется. Вам нужно сохранить ссылку на List, возвращаемую Arrays.asList, а затем распечатать значения этого List (а не значения массива) после shuffle it.

...