Los iteradores de lista garantizan en primer lugar que obtiene los elementos de la lista en el orden interno de la lista (también conocido como orden de inserción ). Más específicamente, está en el orden en que ha insertado los elementos o en cómo ha manipulado la lista. La ordenación puede verse como una manipulación de la estructura de datos, y hay varias formas de ordenar la lista.
Ordenaré las formas en el orden de utilidad tal como lo veo personalmente:
1. Considere usar Set
o Bag
colecciones en su lugar
NOTA: pongo esta opción en la parte superior porque esto es lo que normalmente quieres hacer de todos modos.
Un conjunto ordenado clasifica automáticamente la colección en la inserción , lo que significa que realiza la clasificación mientras agrega elementos a la colección. También significa que no necesita ordenarlo manualmente.
Además, si está seguro de que no necesita preocuparse por (o tener) elementos duplicados, puede usar el TreeSet<T>
en su lugar. Implementa SortedSet
e NavigableSet
interactúa y funciona como probablemente esperarías de una 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"
Si no desea el orden natural, puede usar el parámetro constructor que toma a Comparator<T>
.
Alternativamente, puede usar Multisets (también conocidos como Bolsas ) , es decir, Set
que permite elementos duplicados, y hay implementaciones de terceros de ellos. Más notablemente de las bibliotecas de guayaba hay un TreeMultiset
, que funciona mucho como el TreeSet
.
2. Ordene su lista con Collections.sort()
Como se mencionó anteriormente, la clasificación de List
s es una manipulación de la estructura de datos. Entonces, para situaciones en las que necesita "una fuente de verdad" que se clasificará de varias maneras, entonces ordenarlas manualmente es el camino a seguir.
Puedes ordenar tu lista con el java.util.Collections.sort()
método. Aquí hay un ejemplo de código sobre cómo:
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
Un beneficio claro es que puede usarlo Comparator
en el sort
método. Java también proporciona algunas implementaciones para Comparator
, como la Collator
que es útil para cadenas de clasificación sensibles a la configuración regional. Aquí hay un ejemplo:
Collator usCollator = Collator.getInstance(Locale.US);
usCollator.setStrength(Collator.PRIMARY); // ignores casing
Collections.sort(strings, usCollator);
Ordenar en entornos concurrentes
Sin embargo, tenga en cuenta que el uso del sort
método no es amigable en entornos concurrentes, ya que la instancia de la colección será manipulada, y debería considerar el uso de colecciones inmutables. Esto es algo que Guava ofrece en la Ordering
clase y es simple:
List<string> sorted = Ordering.natural().sortedCopy(strings);
3. Envuelva su lista con java.util.PriorityQueue
Aunque no hay una lista ordenada en Java, hay una cola ordenada que probablemente funcione igual de bien para usted. Es la java.util.PriorityQueue
clase.
Nico Haase enlazó en los comentarios a una pregunta relacionada que también responde a esto.
En una colección ordenada, lo más probable es que no desee manipular la estructura de datos interna, por lo que PriorityQueue no implementa la interfaz Lista (porque eso le daría acceso directo a sus elementos).
Advertencia sobre el PriorityQueue
iterador
La PriorityQueue
clase implementa las interfaces Iterable<E>
y Collection<E>
para que pueda iterarse como de costumbre. Sin embargo, no se garantiza que el iterador devuelva elementos en el orden ordenado. En cambio (como señala Alderath en los comentarios) necesita hacer poll()
cola hasta que esté vacío.
Tenga en cuenta que puede convertir una lista en una cola prioritaria a través del constructor que toma cualquier colección :
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. Escribe tu propia SortedList
clase
NOTA: No debería tener que hacer esto.
Puede escribir su propia clase Lista que se ordena cada vez que agrega un nuevo elemento. Esto puede hacer que el cálculo sea bastante pesado dependiendo de su implementación y no tiene sentido , a menos que desee hacerlo como un ejercicio, debido a dos razones principales:
- Rompe el contrato que
List<E>
tiene la interfaz porque los add
métodos deben garantizar que el elemento residirá en el índice que el usuario especifique.
- ¿Por qué reinventar la rueda? En su lugar, debe usar TreeSet o Multisets como se señala en el primer punto anterior.
Sin embargo, si desea hacerlo como ejercicio, aquí hay una muestra de código para comenzar, utiliza la AbstractList
clase abstracta:
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();
}
}
Tenga en cuenta que si no ha anulado los métodos que necesita, las implementaciones predeterminadas de AbstractList
arrojarán UnsupportedOperationException
s.