2009-02-24 22 views
202

Estoy usando TreeBidiMap de la biblioteca Apache Collections. Quiero ordenar esto en los valores que son doubles.¿Cómo convertir una colección a la lista?

Mi método consiste en recuperar un Collection de los valores usando:

Collection coll = themap.values(); 

que naturalmente funciona bien.

pregunta principal: ahora quiero saber cómo puedo convertir/molde (no estoy seguro que es correcto) coll en un List por lo que se puede clasificar?

entonces tengo la intención de iterar sobre el objeto List ordenados, que debe estar en orden y conseguir las llaves apropiadas de la TreeBidiMap (themap) utilizando themap.getKey(iterator.next()) donde el iterador habrá terminado la lista de doubles.

+4

Es posible que desee evitar este paso directamente utilizando algún tipo de SortedMap, por lo que las entradas están en orden natural de las claves que se utiliza. El TreeMap propio de Java implementa SortedMap. –

+0

'TreeBidiMap' es un' OrderedMap', el orden debería estar bien. La clasificación requerida en la pregunta es sobre valores, no sobre claves. – Vlasec

Respuesta

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

Como Erel Segal Halevi dice más abajo, si coll ya hay una lista, puede omitir el paso uno. Pero eso dependería de las partes internas de TreeBidiMap.

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

Solo para tener en cuenta que existen dos efectos secundarios en los dos enfoques: enviar la colección a una lista y ordenarla también clasificará la colección original; crear una copia no lo hará. – Barney

+0

Este enfoque degrada el rendimiento en gran medida si se usa repetidamente. Vea mi respuesta para una solución que funciona sobre la marcha, se trata de una colección personalizada. – Vlasec

58

Algo como esto debería funcionar, llamando a la ArrayList constructor que tiene una colección:

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

¿Falta una referencia para acceder a ArrayList? –

+0

@Zach: mmhh buen punto. Sabía que había una razón para que yo marcara esto como CW. Por cierto, la ans de Paul es la única. No sé por qué solo tiene mi uv. – OscarRyz

29

creo que la respuesta de Pablo Tomblin puede ser un desperdicio en el caso coll ya es una lista, ya que se crea una nueva lista y copia todos los elementos. Si coll contiene muchos elementos, esto puede llevar mucho tiempo.

Mi sugerencia es:

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

@Kunigami: Creo que puede ser confundido sobre el método de guayaba newArrayList. No verifica si el Iterable es un tipo de Lista y simplemente devuelve la Lista dada tal como está. Se siempre crea una nueva 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

¿Cómo no se vota más? La respuesta de Kunigami es incorrecta (en la medida en que asume la implementación subyacente). – GreenieMeanie

-1

Aquí es una solución subóptima como una sola línea:

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

Lo que se solicita es una operación bastante costy, asegúrese de que usted don' Necesito hacerlo a menudo (por ejemplo, en un ciclo).

De lo contrario, puede crear una colección personalizada. Se me ocurrió uno que tiene su TreeBidiMap y TreeMultiset debajo del capó. Implemente solo lo que necesita y se preocupe por la integridad de los datos.

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. 
} 

De esta manera, usted tiene un ordenadosMultiset regresaron de values(). Sin embargo, si necesita que sea una lista (por ejemplo, necesita el método de matriz get(index)), tendría que inventar algo más complejo.

4

Creo que se puede escribir como tal:

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

Mejor forma de evitar el casting – Stackee007

Cuestiones relacionadas