2010-10-20 19 views
21

¿Por qué mi código no funciona?¿Por qué Collections.shuffle() falla para mi matriz?

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

El resultado es: 0 1 2 3 4 5 6 7 8 9.

que estaba esperando una secuencia de barajado al azar.

Respuesta

40

Arrays.asList() no se puede aplicar a los arrays de tipo primitivo como se espera. Cuando se aplica a int[], Arrays.asList() produce una lista de int[] s en lugar de la lista de Integer s. Por lo tanto, baraja una lista recién creada de int[].

Este es un comportamiento sutil de argumentos variados y genéricos en Java. Arrays.asList() está declarada como

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

lo tanto, puede tomar varios argumentos de algún tipo T y producir una lista que contiene estos argumentos, o puede tomar un argumento de tipo T[] y devolver una lista de respaldo de esta matriz (que es como los argumentos variados funcionan).

Sin embargo, la última opción sólo funciona cuando T es un tipo de referencia (es decir, no un primitivo tipo tal como int), debido a que sólo los tipos de referencia se pueden utilizar como parámetros de tipo en genéricos (y T es un parámetro de tipo).

Por lo tanto, si pasa int[], obtiene T = int[], y su código no funciona como se esperaba. Pero si se pasa matriz de tipo de referencia (por ejemplo, Integer[]), se obtiene T = Integer y todo funciona:

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

¡GUAU! Pero todos dijeron que los cambios se aplicaron a la lista, no con la matriz arr. ¿Por qué funciona esto? – Dmitry

+3

Porque Arrays.asList() crea una nueva lista respaldada por la matriz. No copia la matriz como otros han indicado. Cada cambio en la lista devuelta por Arrays.asList() también cambia la matriz que lo respalda. – ILMTitan

+0

Entendido ahora. Pero ¿por qué eso no funciona con los tipos primitivos? – Dmitry

-2

Eso no funciona porque la llamada a shuffle está operando en List devuelta por Arrays.asList, no en la matriz subyacente. Por lo tanto, cuando iteras sobre la matriz para imprimir los valores, nada ha cambiado. Lo que quiere hacer es guardar una referencia al List devuelto por Arrays.asList, y luego imprimir los valores de ese List (en lugar de los valores de la matriz) después de shuffle.

+0

La API dice: "Devuelve una lista de tamaño fijo respaldada por la matriz especificada. (Cambios en la lista devuelta" escribir "en la matriz.)" - http://download.oracle.com/javase/6 /docs/api/java/util/Arrays.html#asList(T ...) – Jon

+0

¡Gracias por la respuesta inmediata! – Dmitry

+0

Incorrecto, cualquier cambio realizado en la lista creada por 'Arrays.asList()' se realiza en la matriz en sí; la lista usa esa matriz para almacenar los elementos. El problema es que 'asList' no puede crear una lista de primitivas, por lo que crea una lista con un elemento: la matriz misma. Funcionaría para una matriz con elementos no primitivos (por ejemplo, entero). –

-3

almacenar la lista resturned por Arrays.asList y orden aleatorio que ...

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

es mucho mejor usar tipos genéricos en lugar de tipos crudos – duduamar

+0

-1 Incorrecto, ver otras respuestas. – sleske

6

Trate de añadir esta línea de código para su prueba:

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

Se hará Vea que está imprimiendo un solo elemento List.

El uso de Arrays.asList en una matriz primitiva causa asList para tratar el int[] como un solo objeto en lugar de una matriz. Devuelve List<int[]> en lugar de List<Integer>. Entonces, básicamente estás barajando un único elemento List y por lo tanto, nada se mezcla realmente.

en cuenta que algunas de las respuestas ya dadas están equivocados porque asList devuelve una lista apoyada por la matriz original, nada es copiado - todos los cambios se reflejan en la matriz original.

+0

¿Pero por qué funciona de esa manera con el tipo primitivo int (trata int [] como un solo objeto)? – Dmitry

+0

@Dmitry: las matrices también son 'Object's en Java y supongo que los argumentos de' asList (T ...) 'se interpretan como un simple' Objeto', ya que 'asList' no espera primitivas. – MAK

Cuestiones relacionadas