Como converter uma coleção em lista?

294

Estou usando TreeBidiMapda biblioteca Apache Collections . Eu quero classificar isso nos valores que são doubles.

Meu método é recuperar um Collectiondos valores usando:

Collection coll = themap.values();

O que naturalmente funciona bem.

Pergunta principal: Agora quero saber como posso converter / converter (não tenho certeza qual é o correto) collem um Listpara que possa ser classificado?

Pretendo, então, iterar sobre o Listobjeto classificado , que deve estar em ordem e obter as chaves apropriadas de TreeBidiMap( themap) usando themap.getKey(iterator.next())onde o iterador estará sobre a lista de doubles.

Ankur
fonte
4
Você pode evitar essa etapa usando diretamente algum tipo de SortedMap, para que as entradas estejam na ordem natural das chaves que estão sendo usadas. O próprio TreeMap de Java implementa o SortedMap.
precisa
TreeBidiMapé um OrderedMap, o pedido deve estar ok. A classificação necessária na pergunta é sobre valores, não sobre chaves.
Vlasec 28/05

Respostas:

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

Como Erel Segal Halevi diz abaixo, se coll já é uma lista, você pode pular a etapa um. Mas isso dependeria dos elementos internos do TreeBidiMap.

List list;
if (coll instanceof List)
  list = (List)coll;
else
  list = new ArrayList(coll);
Paul Tomblin
fonte
4
Apenas para observar que existem dois efeitos colaterais nas duas abordagens: converter a coleção em uma lista e, em seguida, classificar também classificará a coleção original; criar uma cópia não.
Barney
Essa abordagem diminui muito o desempenho se usada repetidamente. Veja minha resposta para uma solução que funciona on-the-fly, que envolve uma coleção personalizada.
Vlasec 2/08/16
Isso não resolve o caso quando map.values ​​() retorna uma coleção de "classe interna". O compilador relata que Collections.sort (List <T>) não aceita Collections.sort (List <InnerClass>). A solução foi ainda ao uso:.. List <InnerClass> list = map.values () fluxo () coleta (Collectors.toList ())
Pereira
92

Algo assim deve funcionar, chamando o construtor ArrayList que usa uma Collection:

List theList = new ArrayList(coll);
Jack Leow
fonte
Agradável e simples.
James Gawron
33

Eu acho que a resposta de Paul Tomblin pode ser um desperdício caso coll já seja uma lista, porque criará uma nova lista e copiará todos os elementos. Se coll contém muitos elementos, isso pode levar um longo tempo.

Minha sugestão é:

List list;
if (coll instanceof List)
  list = (List)coll;
else
  list = new ArrayList(coll);
Collections.sort(list);
Erel Segal-Halevi
fonte
21

Eu acredito que você pode escrever assim:

coll.stream().collect(Collectors.toList())
Eyal Ofri
fonte
A melhor maneira de dar a volta lançando
Stackee007
Ótimo! Isso resolveu meu caso. Meu map.values ​​() retorna uma coleção "classe interna". O compilador relatou que Collections.sort (List <T>) não aceita Collections.sort (List <InnerClass>).
Pereira
não funcionou para o meu caso de uso no android. requer API mínima 24
ansh sachdeva
8
Collections.sort( new ArrayList( coll ) );
OscarRyz
fonte
Falta uma referência para acessar ArrayList?
Zach Scrivena
@ Zach: mmhh bom ponto. Eu sabia que havia uma razão para eu marcar isso como CW. Entre ans de Paul é o único. Não sei por que ele tem apenas meu uv.
OscarRyz 24/02/09
4

@Kunigami: Eu acho que você pode estar enganado sobre o newArrayListmétodo da Goiaba . Ele não verifica se o Iterable é um tipo de Lista e simplesmente retorna a Lista como está. Ele sempre cria uma nova 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());
}
Nathan Perrier
fonte
Como isso não é mais votado? A resposta de Kunigami está incorreta (na medida em que assume sobre a implementação subjacente).
procurando
0

O que você solicita é uma operação bastante confortável, verifique se você não precisa fazer isso com frequência (por exemplo, em um ciclo).

Caso contrário, você pode criar uma coleção personalizada. Eu vim com um que tem o seu TreeBidiMape TreeMultisetsob o capô. Implemente apenas o que você precisa e se preocupa com a integridade dos dados.

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

Dessa forma, você retornou uma classificação Multiset de values(). No entanto, se você precisar que seja uma lista (por exemplo, você precisa do get(index)método de matriz ), teria que inventar algo mais complexo.

Vlasec
fonte
keySet()e values()são vistas para o original Map, portanto, quando elas são modificadas, o apoio também Mapprecisa ser modificado, sua solução não suporta isso
Lino
-4

Aqui está uma solução abaixo do ideal como uma linha:

Collections.list(Collections.enumeration(coll));
Århus
fonte