Come ordinare un set in un elenco in Java?


169

In Java, ho un Set, e voglio trasformarlo in un ordinato List. C'è un metodo nel java.util.Collectionspacchetto che lo farà per me?

Risposte:


214

La risposta fornita dall'OP non è la migliore. È inefficiente, in quanto crea un nuovo List e nuovo array un nuovo array non necessario. Inoltre, genera avvisi "non controllati" a causa dei problemi di sicurezza del tipo intorno agli array generici.

Invece, usa qualcosa del genere:

public static
<T extends Comparable<? super T>> List<T> asSortedList(Collection<T> c) {
  List<T> list = new ArrayList<T>(c);
  java.util.Collections.sort(list);
  return list;
}

Ecco un esempio di utilizzo:

Map<Integer, String> map = new HashMap<Integer, String>();
/* Add entries to the map. */
...
/* Now get a sorted list of the *values* in the map. */
Collection<String> unsorted = map.values();
List<String> sorted = Util.asSortedList(unsorted);

3
Grazie! That SuppressWarnings mi ha sempre infastidito.
Jeremy Stein,

4
@sunleo La Utilclasse è quella che contiene il asSortedList()metodo che ho scritto. In altre parole, scrivi tu stesso la Utilclasse e inserisci quel codice.
Erickson,

1
ah ah ho pensato che fosse dal pacchetto predefinito come java.util ok grazie.
sunleo,

3
Questa potrebbe essere una bella funzione di utilità generica, ma il fatto è che non è ancora efficiente. Prendi in considerazione l'ordinamento sul posto assicurandoti di avere il tuo set nel contenitore giusto per cominciare. Considera anche l'utilizzo di TreeSet come contenitore diretto dei tuoi dati. Se i tuoi dati devono comunque essere univoci e hai bisogno di un set, allora usa TreeSet, cattura due mosche in uno swat.
YoYo

1
Come nota per le persone che leggono solo la risposta migliore: dai un'occhiata alla risposta di nschum di seguito, che utilizza i flussi di Java 8. Se puoi usare Java 8, provaci. sono più flessibili ed efficienti.
Felk,

74

Set ordinato:

return new TreeSet(setIWantSorted);

o:

return new ArrayList(new TreeSet(setIWantSorted));

Questo è stato il mio primo pensiero, ma il richiedente voleva un elenco
Alex B

@Alex: questo approccio può ancora essere utilizzato; return new ArrayList (new TreeSet (setIWantSorted))
Jonik

1
In realtà ho usato questa soluzione, ma non lo consiglierei. Come afferma la documentazione su TreeSet (consultare download.oracle.com/javase/1.4.2/docs/api/java/util/… ), utilizza in modo efficace il metodo compareTo () anziché il metodo equals (), quindi se si hanno due oggetti nel set che hanno lo stesso risultato equals (), saranno visti come duplicati e, come tali, non verranno aggiunti al TreeSet. Attenzione.
fwielstra,

24
@fwielstra: come si possono avere oggetti uguali nell'input poiché anche l'input è un Set?
Ryanprayogo,

2
@ryanprayogo Vale la pena menzionare, come new TreeSetaccetta Collections, non solo Sets. Non tutti coloro che stanno leggendo questa risposta useranno un Set, anche se è questa la domanda originale.
Chris,

44
List myList = new ArrayList(collection);
Collections.sort(myList);

... Comunque dovrebbe fare il trucco. Aggiungi sapore con Generics dove applicabile.


Avevo uno snippet utile che volevo donare alla community. Quando ho cercato le informazioni, non sono riuscito a trovarle. Stavo cercando di semplificare il lavoro della persona successiva. stackoverflow.com/questions/18557/…
Jeremy Stein,

1
Sì, certo, ma quel link che hai fornito in realtà parla di domande reali (cioè quelle per le quali non hanno la risposta, quindi la trovi). La tua domanda qui era solo per dare la risposta ... Potevo davvero inserire centinaia di domande e rispondere a me stesso; non è questo il punto!
Seb

5
@Seb: non sono d'accordo. Non vedo nulla di sbagliato in questa domanda. Ovviamente non era una domanda estremamente semplice, e ora conosce un modo migliore di prima!
Michael Myers

3
E ' stata una vera e propria domanda, ma ho trovato la risposta me stesso dopo che Google si avvicinò a breve. Stackoverflow non esisteva al momento. L'ho pubblicato sul mio sito Web e ha aiutato qualcun altro, quindi ho pensato che potesse essere utile qui.
Jeremy Stein,

Bonus: e se ti capita di ordinare il tuo tipo di oggetto, puoi sempre implementare Comparablee sovrascrivere il compareTometodo.
nabster

42

Ecco come puoi farlo con i flussi di Java 8:

mySet.stream().sorted().collect(Collectors.toList());

o con un comparatore personalizzato:

mySet.stream().sorted(myComparator).collect(Collectors.toList());

9

Sempre sicuro utilizzare l'interfaccia Comparator o Comparable per fornire l'implementazione dell'ordinamento (se l'oggetto non è una classe String o Wrapper per i tipi di dati primitivi). Ad esempio per un'implementazione di comparatore per ordinare i dipendenti in base al nome

    List<Employees> empList = new LinkedList<Employees>(EmpSet);

    class EmployeeComparator implements Comparator<Employee> {

            public int compare(Employee e1, Employee e2) {
                return e1.getName().compareTo(e2.getName());
            }

        }

   Collections.sort(empList , new EmployeeComparator ());

Comparator è utile quando è necessario disporre di un algoritmo di ordinamento diverso sullo stesso oggetto (pronunciare emp name, emp salary, ecc.). L'ordinamento in modalità singola può essere implementato utilizzando l'interfaccia Comparable nell'oggetto richiesto.


5

Non esiste un singolo metodo per farlo. Usa questo:

@SuppressWarnings("unchecked")
public static <T extends Comparable> List<T> asSortedList(Collection<T> collection) {
  T[] array = collection.toArray(
    (T[])new Comparable[collection.size()]);
  Arrays.sort(array);
  return Arrays.asList(array);
}

C'è anche una funzione Collections.sort, ma penso che faccia la stessa cosa. +1 comunque.
CookieOfFortune,

1
Collections.sort accetta un elenco come parametro.
Jeremy Stein,

3

È possibile convertire un set in un ArrayList, dove è possibile ordinare l' ArrayListutilizzo Collections.sort(List).

Ecco il codice:

keySet = (Set) map.keySet();
ArrayList list = new ArrayList(keySet);     
Collections.sort(list);

3
TreeSet sortedset = new TreeSet();
sortedset.addAll(originalset);

list.addAll(sortedset);

dove originalset = set non ordinato e list = l'elenco da restituire


TreeSet inoltre annulla la duplicazione dell'elenco, il che può comportare un risultato errato se non lo si assume.
anthonymonori il

2

@Jeremy Stein Volevo implementare lo stesso codice. Anche io volevo ordinare il set in list, quindi invece di usare Set ho convertito i valori set in List e li ho ordinati in base alla variabile. Questo codice mi ha aiutato,

set.stream().sorted(Comparator.comparing(ModelClassName::sortingVariableName)).collect(Collectors.toList());

0

Sto usando questo codice, che trovo più pratico della risposta accettata sopra:

List<Thing> thingList = new ArrayList<>(thingSet);
thingList.sort((thing1, thing2) -> thing1.getName().compareToIgnoreCase(thing2.getName()));
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.