Java Set mantiene l'ordine?


179

Un set Java mantiene l'ordine? Un metodo mi sta restituendo un set e presumibilmente i dati sono ordinati ma iterando sul set, i dati non sono ordinati. C'è un modo migliore per gestirlo? È necessario modificare il metodo per restituire qualcosa di diverso da un set?


3
"Gli elementi non vengono restituiti in un ordine particolare (a meno che questo set non sia un'istanza di una classe che fornisce una garanzia)." è ciò che dice il metodo iteratore per un set. trovato qui
keyser

Risposte:


257

L' Setinterfaccia non fornisce alcuna garanzia d'ordine.

La sua sotto-interfaccia SortedSetrappresenta un set che viene ordinato in base ad alcuni criteri. In Java 6, ci sono due contenitori standard che implementano SortedSet. Sono TreeSete ConcurrentSkipListSet.

Oltre SortedSetall'interfaccia, c'è anche la LinkedHashSetclasse. Ricorda l'ordine in cui gli elementi sono stati inseriti nell'insieme e restituisce i suoi elementi in quell'ordine.


21
Inoltre, a causa del diverso hash delle stringhe in Java 8, cambierà l'ordine predefinito (non ordinato) in set e mappe. Se si fa affidamento su ordini non ordinati, il codice si comporterà in modo diverso in Java 8.
rustyx,

Capisco che la classe che non ordina è normale, ma il comportamento che mi aspettavo era di lasciarli quando venivano introdotti e non confondere con l'ordine, invece mescola gli elementi ogni volta che uno viene aggregato. La tua soluzione non è ottimale appassire perché poi dovrò implementare un'intera struttura affinché vengano ordinate LO STESSO MODO in cui sono state introdotte: S
White_King

@White_King: un set è un concetto matematico che non contiene la nozione di "ordine di inserzione", quindi ha senso che l'interfaccia Java segua le sue convenzioni. Esistono insiemi ordinati ma l'ordine viene specificato da una relazione (comparatore in Java), facendo corrispondere nuovamente la definizione nella teoria degli insiemi con la definizione in Java. Le tue aspettative nel mantenere l'ordine di inserimento probabilmente provengono da elenchi ma i set non sono elenchi.
Konrad Höffner,

103

LinkedHashSet è quello che ti serve.


43
A Listnon è un Set(non garantisce l'unicità dell'adesione).
Espiazione limitata il

10
In molti casi aziendali unici, l'elenco non può essere utilizzato solo per conservare l'ordine anziché impostare. LinkedHashSet mantiene l'ordine e archivia unici.
gubs

18

Come molti membri hanno suggerito di utilizzare LinkedHashSet per conservare l'ordine della raccolta. Puoi avvolgere il tuo set usando questa implementazione.

L' implementazione di SortedSet può essere utilizzata per l'ordinamento ordinato, ma ai fini dell'utente utilizzare LinkedHashSet .

Anche dai documenti,

"Questa implementazione risparmia i suoi clienti dall'ordinamento non specificato, generalmente caotico fornito da HashSet, senza incorrere in un aumento dei costi associati a TreeSet. Può essere utilizzato per produrre una copia di un set con lo stesso ordine dell'originale, indipendentemente dall'originale implementazione di set: "

Fonte: http://docs.oracle.com/javase/6/docs/api/java/util/LinkedHashSet.html


9

Set è solo un'interfaccia. Per mantenere l'ordine, è necessario utilizzare un'implementazione specifica di tale interfaccia e della sottoscheda SortedSet, ad esempio TreeSet o LinkedHashSet. Puoi avvolgere il tuo Set in questo modo:

Set myOrderedSet = new LinkedHashSet(mySet);

7

Ecco un breve riepilogo delle caratteristiche dell'ordine delle Setimplementazioni standard disponibili in Java:

  1. mantenere l'ordine di inserimento: LinkedHashSet e CopyOnWriteArraySet (thread-safe)
  2. mantenere gli elementi ordinati nel set: TreeSet , EnumSet (specifico per enums) e ConcurrentSkipListSet (thread-safe)
  3. non mantiene gli articoli in alcun ordine specifico: HashSet (quello che hai provato)

Per il tuo caso specifico, puoi prima ordinare gli oggetti e poi usare uno di 1 o 2 (molto probabilmente LinkedHashSeto TreeSet). O in alternativa e in modo più efficiente , puoi semplicemente aggiungere dati non ordinati a uno TreeSetche si occuperà automaticamente dell'ordinamento per te.


7

Per conservare l'ordine utilizzare Listo a LinkedHashSet.


1
E ' LinkedHashSet, no ... Map.
Marko Topolnik,

Ho bisogno di un set non di un elenco, ho bisogno di un set che mantenga anche l'ordine di iniezione degli oggetti, credo
White_King

5

Un LinkedHashSet è una versione ordinata di HashSet che mantiene un elenco doppiamente collegato tra tutti gli elementi. Usa questa classe invece di HashSet quando ti preoccupi dell'ordine di iterazione.


3

Dal javadoc per Set.iterator():

Restituisce un iteratore sugli elementi in questo set. Gli elementi non vengono restituiti in un ordine particolare (a meno che questo set non sia un'istanza di una classe che fornisce una garanzia).

E, come già affermato da Shuuchan , a TreeSetè un'implementazione Setche ha un ordine garantito:

Gli elementi vengono ordinati utilizzando il loro ordinamento naturale o tramite un comparatore fornito al momento della creazione impostato, a seconda del costruttore utilizzato.


3

Normalmente impostato non mantiene l'ordine, come HashSet per trovare rapidamente un emelent, ma puoi provare LinkedHashSet che manterrà l'ordine che hai inserito.


1

Ci sono 2 cose diverse.

  1. Ordina gli elementi in un set. Per il quale abbiamo SortedSet e implementazioni simili.
  2. Mantiene l'ordine di inserimento in un set. Per cui è possibile utilizzare LinkedHashSet e CopyOnWriteArraySet (thread-safe).



-2

Solo SortedSetpuò fare l'ordinamento diSet


La domanda riguarda il mantenimento dell'ordine di inserimento (che risulta essere ordinato).
Assylias,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.