2010-10-20 11 views
21

Perché il mio codice non funziona?Perché Collections.shuffle() non riesce per il mio array?

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

Il risultato è: 0 1 2 3 4 5 6 7 8 9.

mi aspettavo una sequenza casualmente alterato.

risposta

40

Arrays.asList() non può essere applicato a un array di tipo primitivo come previsto. Se applicato a int[], Arrays.asList() produce un elenco di int[] s anziché un elenco di Integer s. Pertanto mischia una lista appena creata di int[].

Questo è un comportamento sottile di argomenti variadici e generici in Java. Arrays.asList() è dichiarato come

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

Quindi, può richiedere diversi argomenti di un certo tipo T e produrre una lista contenente questi argomenti, o si può prendere un argomento di tipo T[] e restituire una lista sostenuta da questo array (che è come argomenti variadici funzionano).

Tuttavia, quest'ultima opzione funziona solo quando T è un tipo di riferimento (cioè non un tipo primitivo come int), perché solo tipi di riferimento possono essere utilizzati come parametri tipo a generici (e T è un parametro di tipo).

Quindi, se si passa int[], si ottiene T = int[] e il codice non funziona come previsto. Ma se si passa matrice di tipo di riferimento (ad esempio, Integer[]), si ottiene T = Integer e tutto funziona:

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

WOW !!! Ma tutti hanno detto che le modifiche applicate per la lista, non con l'array arr. Perché funziona? – Dmitry

+3

Poiché Arrays.asList() crea un nuovo elenco supportato dall'array. Non copia l'array come altri hanno affermato. Ogni modifica alla lista restituita da Arrays.asList() cambia anche l'array che la supporta. – ILMTitan

+0

Capito ora. Ma perché questo non funziona con i tipi primitivi? – Dmitry

-2

Non funziona perché la chiamata a shuffle è attiva su List restituita da Arrays.asList, non sull'array sottostante. Pertanto, quando si esegue l'iterazione sull'array per stampare i valori, non è cambiato nulla. Quello che si desidera fare è salvare un riferimento a List restituito da Arrays.asList e quindi stampare i valori di tale List (anziché i valori dell'array) dopo averlo shuffle.

+0

L'API dice: "Restituisce un elenco di dimensioni fisse supportato dall'array specificato. (Le modifiche all'elenco restituito" write through "all'array.)" - http://download.oracle.com/javase/6 /docs/api/java/util/Arrays.html#asList(T ...) – Jon

+0

Grazie per la risposta immediata! – Dmitry

+0

Sbagliato, tutte le modifiche apportate alla lista creata da 'Arrays.asList()' sono apportate alla matrice stessa - la lista usa quella matrice per memorizzare gli elementi. Il problema è che 'asList' non può creare una lista di primitive, quindi crea una lista con un elemento: la matrice stessa. Funzionerebbe per un array con non primitivi (ad esempio intero). –

-3

memorizzare l'elenco resturned da Arrays.asList e shuffle che ...

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

È molto meglio utilizzare tipi generici anziché tipi non elaborati – duduamar

+0

-1 Errato, vedere altre risposte. – sleske

6

Prova ad aggiungere questa riga di codice per il test:

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

Avrete vedi che stai stampando un singolo elemento List.

L'utilizzo di Arrays.asList su una matrice primitiva causa asList per il trattamento di int[] come un singolo oggetto anziché una matrice. Restituisce un List<int[]> anziché uno List<Integer>. Quindi, stai basicamente mischiando un singolo elemento List e quindi niente viene mescolato davvero.

Si noti che alcune delle risposte già fornite sono errate perché asList restituisce un elenco supportato dall'array originale, non viene copiato nulla - tutte le modifiche si riflettono nell'array originale.

+0

Ma perché funziona in modo simile al tipo primitivo int (considera int [] come un singolo oggetto)? – Dmitry

+0

@Dmitry: Gli array sono anche 'Object's in Java e suppongo che gli argomenti di' asList (T ...) 'vengano interpretati come un semplice' Object', poiché 'asList' non si aspetta le primitive. – MAK

Problemi correlati