2009-02-24 7 views
202

Sto usando TreeBidiMap dalla libreria Apache Collections. Voglio ordinare questo sui valori che sono doubles.Come convertire una collezione in lista?

Il mio metodo è quello di recuperare un Collection dei valori utilizzando:

Collection coll = themap.values(); 

Quale funziona naturalmente bene.

Domanda principale: Ora voglio sapere come posso convertire/cast (non sono sicuro che è corretto) coll in un List in modo che possa essere ordinata?

Ho quindi intenzione di iterare l'ordinato List oggetto, che dovrebbe essere in ordine e ottenere le chiavi appropriati dal TreeBidiMap (themap) utilizzando themap.getKey(iterator.next()) dove l'iteratore sarà finita l'elenco dei doubles.

+4

Si potrebbe voler evitare questo passaggio utilizzando direttamente una sorta di SortedMap, in modo che le voci sono in ordine naturale delle chiavi in ​​uso. La TreeMap di Java implementa SortedMap. –

+0

'TreeBidiMap' è un' OrderedMap', l'ordine dovrebbe essere ok. L'ordinamento richiesto nella domanda è sui valori, non sulle chiavi. – Vlasec

risposta

365
List list = new ArrayList(coll); 
Collections.sort(list); 

Come dice Erel Segal Halevi di seguito, se coll è già un elenco, è possibile saltare il passaggio uno. Ma ciò dipenderebbe dall'interno di TreeBidiMap.

List list; 
if (coll instanceof List) 
    list = (List)coll; 
else 
    list = new ArrayList(coll); 
+1

Solo per notare che ci sono diversi effetti collaterali ai due approcci: il cast della collezione in una lista e poi l'ordinamento anche la raccolta originale; la creazione di una copia non lo farà. – Barney

+0

Questo approccio riduce notevolmente le prestazioni se utilizzato ripetutamente. Vedi la mia risposta per una soluzione che funziona al volo, coinvolge una collezione personalizzata. – Vlasec

58

Qualcosa del genere dovrebbe funzionare, chiamando il ArrayList constructor che prende una Collezione:

List theList = new ArrayList(coll); 
7
Collections.sort(new ArrayList(coll)); 
+0

Manca un riferimento per accedere a ArrayList? –

+0

@Zach: mmhh buon punto. Sapevo che c'era un motivo per me per contrassegnare questo come CW. A proposito, Paul's ans è l'unico. Non so perché ha solo il mio uv. – OscarRyz

29

penso la risposta di Paolo Tomblin può essere dispendioso in caso Coll è già una lista, perché lo farà crea una nuova lista e copia tutti gli elementi. Se coll contiene molti elemeents, questo può richiedere molto tempo.

Il mio suggerimento è:

List list; 
if (coll instanceof List) 
    list = (List)coll; 
else 
    list = new ArrayList(coll); 
Collections.sort(list); 
4

@Kunigami: penso che potrebbe essere scambiato sul metodo di Guava newArrayList. Non controlla se l'Iterable è un tipo di lista e semplicemente restituisce l'Elenco dato così com'è. E sempre crea una nuova lista:

@GwtCompatible(serializable = true) 
public static <E> ArrayList<E> newArrayList(Iterable<? extends E> elements) { 
    checkNotNull(elements); // for GWT 
    // Let ArrayList's sizing logic work, if possible 
    return (elements instanceof Collection) 
     ? new ArrayList<E>(Collections2.cast(elements)) 
     : newArrayList(elements.iterator()); 
} 
+0

In che modo questo non viene più votato? La risposta di Kunigami è errata (per quanto si suppone sull'implementazione sottostante). – GreenieMeanie

-1

Ecco una soluzione sub-ottimale come un one-liner:

Collections.list(Collections.enumeration(coll)); 
1

Quello che si richiede è piuttosto un'operazione costy, assicurarsi che si don' t necessario farlo spesso (ad es. in un ciclo).

In caso contrario, è possibile creare una raccolta personalizzata. Ne ho trovato uno che ha il tuo TreeBidiMap e TreeMultiset sotto il cofano. Implementa solo ciò di cui hai bisogno e cura dell'integrità dei dati.

class MyCustomCollection implements Map<K, V> { 
    TreeBidiMap<K, V> map; 
    TreeMultiset<V> multiset; 
    public V put(K key, V value) { 
     removeValue(map.put(key, value)); 
     multiset.add(value); 
    } 
    public boolean remove(K key) { 
     removeValue(map.remove(key)); 
    } 
    /** removes value that was removed/replaced in map */ 
    private removeValue(V value) { 
     if (value != null) { 
      multiset.remove(value); 
     } 
    } 
    public Set keySet() { 
     return map.keySet(); 
    } 
    public Multiset values() { 
     return multiset; 
    } 
    // many more methods to be implemented, e.g. count, isEmpty etc. 
} 

In questo modo, hanno un ordinatoMultiset tornato da values(). Tuttavia, se è necessario che sia un elenco (ad esempio, è necessario il metodo array get(index)), è necessario inventare qualcosa di più complesso.

4

Credo che si può scrivere come tale:

coll.stream().collect(Collectors.toList()) 
+0

Un modo migliore per aggirare il casting – Stackee007