Os iteradores da lista garantem, em primeiro lugar, que você obtenha os elementos da lista na ordem interna da lista (também conhecida como ordem de inserção ). Mais especificamente, está na ordem em que você inseriu os elementos ou em como você manipulou a lista. A classificação pode ser vista como uma manipulação da estrutura de dados e há várias maneiras de classificar a lista.
Vou ordenar os caminhos na ordem de utilidade que eu pessoalmente vejo:
1. Considere usar Set
ou Bag
coleções
NOTA: Coloquei essa opção no topo, porque é isso que você normalmente deseja fazer.
Um conjunto classificado classifica automaticamente a coleção na inserção , o que significa que faz a classificação enquanto você adiciona elementos à coleção. Isso também significa que você não precisa classificá-lo manualmente.
Além disso, se você tiver certeza de que não precisa se preocupar (ou ter) elementos duplicados, poderá usá-lo TreeSet<T>
. Ele implementa SortedSet
e NavigableSet
interfaces e obras como você provavelmente esperaria de uma lista:
TreeSet<String> set = new TreeSet<String>();
set.add("lol");
set.add("cat");
// automatically sorts natural order when adding
for (String s : set) {
System.out.println(s);
}
// Prints out "cat" and "lol"
Se você não deseja a ordem natural, pode usar o parâmetro construtor que recebe a Comparator<T>
.
Como alternativa, você pode usar Multisets (também conhecidos como Bags ) , ou seja, Set
que permite elementos duplicados, e existem implementações de terceiros. Mais notavelmente das bibliotecas do Guava, existe um TreeMultiset
, que funciona muito como o TreeSet
.
2. Classifique sua lista com Collections.sort()
Como mencionado acima, a classificação de List
s é uma manipulação da estrutura de dados. Portanto, para situações em que você precisa de "uma fonte de verdade" que será classificada de várias maneiras, classificá-la manualmente é o caminho a percorrer.
Você pode classificar sua lista com o java.util.Collections.sort()
método Aqui está um exemplo de código sobre como:
List<String> strings = new ArrayList<String>()
strings.add("lol");
strings.add("cat");
Collections.sort(strings);
for (String s : strings) {
System.out.println(s);
}
// Prints out "cat" and "lol"
Usando comparadores
Um benefício claro é que você pode usar Comparator
no sort
método. Java também fornece algumas implementações para Comparator
as Collator
que são úteis para seqüências de classificação sensíveis ao código do idioma. Aqui está um exemplo:
Collator usCollator = Collator.getInstance(Locale.US);
usCollator.setStrength(Collator.PRIMARY); // ignores casing
Collections.sort(strings, usCollator);
Classificação em ambientes simultâneos
Observe, porém, que o uso do sort
método não é amigável em ambientes simultâneos, pois a instância da coleção será manipulada e, em vez disso, você deve considerar o uso de coleções imutáveis. Isso é algo que o Guava fornece na Ordering
classe e é uma linha simples:
List<string> sorted = Ordering.natural().sortedCopy(strings);
3. Envolva sua lista com java.util.PriorityQueue
Embora não exista uma lista classificada em Java, existe uma fila classificada que provavelmente funcionaria bem para você. É a java.util.PriorityQueue
classe.
Nico Haase vinculou nos comentários a uma pergunta relacionada que também responde a isso.
Em uma coleção classificada, você provavelmente não deseja manipular a estrutura de dados interna, e é por isso que o PriorityQueue não implementa a interface List (porque isso lhe daria acesso direto a seus elementos).
Advertência sobre o PriorityQueue
iterador
A PriorityQueue
classe implementa as interfaces Iterable<E>
e Collection<E>
para que possa ser iterada como de costume. No entanto, não é garantido que o iterador retorne elementos na ordem classificada. Em vez disso (como Alderath aponta nos comentários), você precisa ficar poll()
na fila até ficar vazio.
Observe que você pode converter uma lista em uma fila de prioridade por meio do construtor que utiliza qualquer coleção :
List<String> strings = new ArrayList<String>()
strings.add("lol");
strings.add("cat");
PriorityQueue<String> sortedStrings = new PriorityQueue(strings);
while(!sortedStrings.isEmpty()) {
System.out.println(sortedStrings.poll());
}
// Prints out "cat" and "lol"
4. Escreva sua própria SortedList
turma
NOTA: Você não precisa fazer isso.
Você pode escrever sua própria classe List, que é classificada sempre que adicionar um novo elemento. Isso pode tornar a computação pesada, dependendo da sua implementação e não faz sentido , a menos que você queira fazer isso como um exercício, por dois motivos principais:
- Ele quebra o contrato que a
List<E>
interface possui, porque os add
métodos devem garantir que o elemento resida no índice especificado pelo usuário.
- Por que reinventar a roda? Você deve usar o TreeSet ou Multisets, como indicado no primeiro ponto acima.
No entanto, se você quiser fazer isso como um exercício, aqui está um exemplo de código para começar, ele usa a AbstractList
classe abstract:
public class SortedList<E> extends AbstractList<E> {
private ArrayList<E> internalList = new ArrayList<E>();
// Note that add(E e) in AbstractList is calling this one
@Override
public void add(int position, E e) {
internalList.add(e);
Collections.sort(internalList, null);
}
@Override
public E get(int i) {
return internalList.get(i);
}
@Override
public int size() {
return internalList.size();
}
}
Observe que se você não substituiu os métodos necessários, as implementações padrão de AbstractList
irão lançar UnsupportedOperationException
s.