Como ordeno um conjunto para uma lista em Java?

169

Em Java, eu tenho um Sete quero transformá-lo em um classificado List. Existe um método no java.util.Collectionspacote que fará isso por mim?

Jeremy Stein
fonte

Respostas:

214

A resposta fornecida pelo OP não é a melhor. É ineficiente, pois cria uma nova List e uma nova matriz desnecessária. Além disso, gera avisos "não verificados" devido aos problemas de segurança de tipo em torno de matrizes genéricas.

Em vez disso, use algo como isto:

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

Aqui está um exemplo de uso:

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);
erickson
fonte
3
Obrigado! Que SuppressWarnings sempre me incomodou.
21413 Jeremy Stein
4
@sunleo A Utilclasse é a que contém o asSortedList()método que escrevi. Em outras palavras, você mesmo escreve a Utilclasse e insere esse código.
21712
1
ha ha eu pensei que é do pacote padrão como java.util ok obrigado.
sunleo
3
Essa pode ser uma boa função genérica do utilitário, mas o fato é que ainda não é eficiente. Considere a classificação no local, certificando-se de ter seu conjunto no contêiner certo para começar. Considere também o uso do TreeSet como um contêiner direto de seus dados. Se seus dados precisarem ser exclusivos e você precisar de um conjunto, use o TreeSet, pegue duas moscas em um golpe.
YoYo
1
Como uma observação para as pessoas que estão apenas lendo a resposta principal: Veja a resposta de nschum abaixo, que usa os fluxos do Java 8. Se você pode usar o Java 8, vá em frente. eles são mais flexíveis e eficientes.
Felk
74

Conjunto classificado:

return new TreeSet(setIWantSorted);

ou:

return new ArrayList(new TreeSet(setIWantSorted));
Steve B.
fonte
Este foi o meu primeiro pensamento, mas o consulente queria uma Lista
Alex B
@ Alex: Essa abordagem ainda pode ser usada; voltar new ArrayList (novo TreeSet (setIWantSorted))
Jonik
1
Na verdade, usei essa solução, mas não aconselho isso. Como a documentação em TreeSet indica (consulte download.oracle.com/javase/1.4.2/docs/api/java/util/… ), ela efetivamente usa o método compareTo () em vez do método equals () - portanto, se você tiver dois objetos no conjunto que tenham o mesmo resultado igual a (), eles serão vistos como duplicados e, como tal, não serão adicionados ao TreeSet. Cuidado.
fwielstra
24
@fwielstra: Como você pode ter objetos iguais na entrada, já que a entrada também é uma Set?
Ryanprayogo 27/07
2
@ryanprayogo Vale a pena mencionar, como new TreeSetaceita Collections, não apenas Sets. Nem todo mundo que está lendo esta resposta usa um Set, mesmo que seja o que a pergunta original está fazendo.
21415 Chris
44
List myList = new ArrayList(collection);
Collections.sort(myList);

... deve fazer o truque no entanto. Adicione sabor com genéricos, quando aplicável.

Esko
fonte
Eu tinha um trecho útil que queria doar para a comunidade. Quando procurei as informações, não consegui encontrá-las. Eu estava tentando facilitar o trabalho da próxima pessoa. stackoverflow.com/questions/18557/…
Jeremy Stein
1
Sim, claro, mas esse link que você forneceu está realmente falando de perguntas reais (ou seja, aquelas para as quais não há resposta, então encontre-a). Sua pergunta aqui era apenas para dar a resposta ... Na verdade, eu poderia inserir centenas de perguntas e me responder; essa não é a questão!
214/09 Seb
5
@ Seeb: eu discordo. Não vejo nada de errado com esta pergunta. Obviamente não era uma pergunta extremamente simples, e agora ele conhece um caminho melhor do que antes!
Michael Myers
3
Ele foi uma questão real, mas eu encontrei a resposta me depois que o Google veio acima do short. O Stackoverflow não existia no momento. Eu o publiquei no meu site e ajudou alguém, então achei que poderia ser útil aqui.
Jeremy Stein
Bônus: E se você estiver classificando seu próprio tipo de objeto, poderá sempre implementar Comparablee substituir o compareTométodo.
nabster 17/01
42

Veja como você pode fazer isso com o Streams do Java 8:

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

ou com um comparador personalizado:

mySet.stream().sorted(myComparator).collect(Collectors.toList());
nschum
fonte
9

Sempre seguro usar a interface Comparator ou Comparable para fornecer implementação de classificação (se o objeto não for uma classe String ou Wrapper para tipos de dados primitivos). Como exemplo de uma implementação de comparador para classificar funcionários com base no 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 ());

O comparador é útil quando você precisa ter um algoritmo de classificação diferente no mesmo objeto (por exemplo, nome do emp, salário, etc.). A classificação em modo único pode ser implementada usando a interface Comparável no objeto necessário.

Satheesh Cheveri
fonte
5

Não existe um método único para fazer isso. Usa isto:

@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);
}
Jeremy Stein
fonte
Há também uma função Collections.sort, mas acho que faz a mesma coisa. +1 de qualquer maneira.
CookieOfFortune 11/04/09
1
Collections.sort usa uma lista como parâmetro.
Jeremy Stein
3

Você pode converter um conjunto em um ArrayList, onde é possível classificar o ArrayListuso Collections.sort(List).

Aqui está o código:

keySet = (Set) map.keySet();
ArrayList list = new ArrayList(keySet);     
Collections.sort(list);
Amit
fonte
3
TreeSet sortedset = new TreeSet();
sortedset.addAll(originalset);

list.addAll(sortedset);

onde originalset = conjunto não classificado e lista = a lista a ser retornada

Sujith Mohan
fonte
O TreeSet também elimina a lista que pode resultar em resultados incorretos se você não assumir isso.
anthonymonori 12/06
2

@ Jeremy Stein Eu queria implementar o mesmo código. Assim como eu queria classificar o conjunto para a lista, então, em vez de usar o Conjunto, converti os valores do conjunto em Lista e classifique essa lista por uma variável. Esse código me ajudou,

set.stream().sorted(Comparator.comparing(ModelClassName::sortingVariableName)).collect(Collectors.toList());
Deepak Kumbhar
fonte
0

Estou usando esse código, que acho mais prático do que a resposta aceita acima:

List<Thing> thingList = new ArrayList<>(thingSet);
thingList.sort((thing1, thing2) -> thing1.getName().compareToIgnoreCase(thing2.getName()));
nn4l
fonte