2013-09-06 15 views
5

Il seguente codice produce l'out put [1,2] anche se hashset non è ordinato.In che modo questo HashSet produce output ordinato?

Set set = new HashSet(); 
set.add(new Integer(2)); 
set.add(new Integer(1)); 
System.out.println(set); 

Perché è quello?

+0

Utilizzare più casi di test. Includere 20 numeri e vedere se il risultato è lo stesso. – JNL

risposta

8

Questo comportamento è causato da diverse ragioni distinte:

  • Interi hash a se stessi
  • in Java, HashMap s e HashSet s sono supportati da una serie
  • hanno anche modificare gli hash utilizzando il più alto bit per modificare i bit più bassi; se l'hash è nel range 0 ..15, è, pertanto, non modificato
  • quello secchio un oggetto va dipende sui bit inferiori del hash modificato
  • quando l'iterazione di una mappa o di un set, la tabella interna viene digitalizzato sequenzialmente

Quindi, se si aggiungere vari piccoli (16) < interi ad un hashmap/hashset, questo è ciò che accade:

  • intero i trovi hashcode i
  • poiché è meno t han 16, il suo hash modificato è anche i
  • atterra nel secchio n. i
  • quando l'iterazione, i secchi sono visitati in sequenza, quindi se tutto è stato memorizzato ci sono interi piccoli, saranno recuperati in ordine crescente

notare che se il numero iniziale di benne è troppo piccolo, i numeri interi lo sbarco in secchi non numerati dopo di loro:

HashSet<Integer> set = new HashSet<>(4); 
set.add(5); set.add(3); set.add(1); 
for(int i : set) { 
    System.out.print(i); 
} 

stampe 153.

1

A HashSet è una raccolta non ordinata. Non ha garanzie e nessun concetto di "ordinamento". Vedere questa risposta per ulteriori dettagli: What is the difference between Set and List?

È possibile considerare l'utilizzo di un TreeSet se è necessario un Set ordinato ordinato.

C'è anche un LinkedHashSet per un Set ordinato che non è ordinato.

+0

@superEb In realtà ho appena aggiunto quel tocco alla mia risposta. Sembra che ce ne siamo resi conto allo stesso tempo! – Kon

0

A javascript non è possibile che venga ordinato l'elenco set. Utilizzare invece ArrayList. Controllare anche l'API Java Collection per ulteriori riferimenti.

+0

Ma non utilizzare un 'Elenco' se gli elementi devono essere univoci. – superEb

+0

'LinkedHashSet' è in genere una scelta migliore se si desidera una ricerca rapida (a tempo costante) ma con un ordine di iterazione prevedibile. Usa 'ArrayList' solo se stai cercando di risparmiare spazio e puoi tollerare ricerche lente (tempo lineare). –

+0

@Ashwin Si noti che è possibile ottenere il tempo di logaritmo O (log n) cercare le ore per un elenco ordinato utilizzando il metodo 'Collections.binarySearch()'. – Kon

5

A HashSet come da documentazione non garantisce alcun concetto di ordine, quindi quello che stai vedendo potrebbe cambiare molto in un futuro aggiornamento di Java.

Tuttavia, se vi state chiedendo perché Java (a partire da ora) specifica implementazione del HashSet produce il risultato che state vedendo: è perché le Integer di valore 1 hash in una posizione nella tabella di entrata interna di un HashMap che viene prima dello il luogo in cui si verificano gli hash 2 (si noti che uno HashSet è realmente supportato da un valore HashMap con valori arbitrari). Questo ha senso dal momento che il codice hash di un oggetto Integer è solo il suo valore.

In realtà, si può vedere questo anche se si aggiunge ancora più numeri (entro un certo intervallo: la dimensione della tabella di entrata che è 16 per impostazione predefinita):

Set<Integer> set = new HashSet<>(); 
set.add(2); 
set.add(1); 
set.add(4); 
set.add(3); 
set.add(0); 
System.out.println(set); 
 
[0, 1, 2, 3, 4] 

Iterazione nel corso di un HashSet viene eseguito iterando sulla tabella di inserimento interna, il che significa che gli elementi precedenti nella tabella vengono prima.

Problemi correlati