por - sort arraylist java
¿Cómo puedo ordenar este ArrayList de la manera que quiero? (12)
Como otros han declarado, los elementos se ordenarán alfabéticamente por defecto. La solución es definir una clase concreta java.util.Comparator y pasarla como un segundo argumento al método de clasificación. Su comparador deberá analizar los enteros iniciales de las cadenas y compararlos.
Aquí hay un programa de clasificación simple de una ArrayList:
ArrayList<String> list = new ArrayList<String>();
list.add("1_Update");
list.add("11_Add");
list.add("12_Delete");
list.add("2_Create");
Collections.sort(list);
for (String str : list) {
System.out.println(str.toString());
}
Esperaba la salida de este programa como:
1_Update
2_Create
11_Add
12_Delete
Pero cuando ejecuto este programa, obtengo resultados como:
11_Add
12_Delete
1_Update
2_Create
¿Por qué es esto y cómo hago que ArrayList ordene como se muestra en el resultado esperado?
Como se indicó anteriormente, está buscando una implementación de Comparador que implemente un tipo natural. Jeff Atwood escribió una excelente publicación sobre clasificación natural hace algún tiempo, vale la pena leerla.
Si está buscando una implementación de Java, he encontrado que esta es útil: http://www.davekoelle.com/alphanum.html
Cuando ordena este tipo de datos como una cadena, está comparando los mismos caracteres, incluidos los dígitos. Toda la cadena que comienza con "1", por ejemplo, terminará junta. Entonces el orden termina así ...
1 10 100 2 20 200
En ningún momento el tipo "se da cuenta" de que está asignando significado a subconjuntos de la cadena, como los números de longitud variable al frente de la cadena. Al ordenar números como cadenas, rellenar a la izquierda con ceros la cantidad necesaria para cubrir el número más grande puede ayudar, pero en realidad no resuelve el problema cuando no controla los datos, como en su ejemplo. En ese caso, el género sería ...
001 002 010 020 100 200
El algoritmo de comparación de cadenas compara cada carácter a la vez. 1
tipo antes de 2
. No importa que sea seguido por un 1
o un 2
.
Entonces 100
clasificarían antes de 2
. Si no desea este comportamiento, necesita un algoritmo de comparación que maneje este caso.
Está haciendo una comparación lexicográfica. Compara el primer personaje de cada cadena clasificándolos. Luego compara la segunda cadena de aquellos con el mismo primer charater. Cuando compara el carácter ''_'' con un número, tiene un valor mayor que cualquier otro número, como 8> 7 y a> 9. Recuerde que está haciendo una comparación de caracteres y no una comparación numérica.
Hay formas de implementar su propio enrutamiento de clasificación personalizado, que puede ser mejor que cambiar el nombre de los nombres de su secuencia de comandos.
Si cambiar el nombre de los nombres de su secuencia de comandos es una opción, esto puede permitir el uso de otras herramientas de secuencia de comandos. Un formato puede ser
01_create_table.sql 02_create_index.sql 11_assign_privileges.sql
Al mantener sus dos primeros dígitos en dos caracteres, la comparación lexicográfica funcionará.
Está ordenado como texto (alfabéticamente), no como números. Para evitar esto, podría implementar un comparador personalizado como se sugiere en la respuesta de nsayer.
Los documentos del método Collections.sort () dicen:
Ordena la lista especificada en orden ascendente, según el orden natural de sus elementos.
Lo que significa para cadenas que vas a obtener la lista en orden alfabético. The String 11_assign_privileges.sql viene antes de la cadena 1_create_table.sql y 12_07_insert_static_data.sql viene antes de 1_create_table.sql, etc. Por lo tanto, el programa está funcionando como se esperaba.
Para ordenar Collection.sort () arbitrariamente, puede usar
Collections.sort(List list, Comparator c)
Luego, simplemente implemente un Comparador que divide la cadena y clasifica primero en función del número y luego en el resto o como quiera que se ordene.
Porque las cadenas se ordenan en orden alfabético y el carácter de subrayado es después de los caracteres para los números. Debe proporcionar un comparador que implemente el "Pedido natural" para lograr el resultado deseado.
Puede agregar la interfaz IComparable y luego ordenar por una propiedad específica. Si tiene una colección de artículos de una tienda, por ejemplo, tal vez desee ordenarlos por precio o por categoría, etc. Si desea hacer un pedido por nombre, aquí tiene un ejemplo:
observe cómo ArrayList está ordenado por el nombre de propiedad de los artículos. Si no agrega el IComparable, cuando use el método de ordenación arrojará un error.
static void Main(string[] args)
{
ArrayList items = new ArrayList();
items.Add(new Item("book", 12.32));
items.Add(new Item("cd", 16.32));
items.Add(new Item("bed", 124.2));
items.Add(new Item("TV", 12.32));
items.Sort();
foreach (Item temp in items)
Console.WriteLine("Name:{0} Price:{1}", temp.name, temp.price);
Console.Read();
}
class Item: IComparable
{
public string name;
public double price;
public Item(string _name, double _price)
{
this.name = _name;
this.price = _price;
}
public int CompareTo(object obj)
{
//note that I use the name property I may use a different one
int temp = this.name.CompareTo(((Item)obj).name);
return temp;
}
}
Puede escribir un comparador personalizado:
Collections.sort(list, new Comparator<String>() {
public int compare(String a, String b) {
return Integer.signum(fixString(a) - fixString(b));
}
private int fixString(String in) {
return Integer.parseInt(in.substring(0, in.indexOf(''_'')));
}
});
Todos ya han señalado que la explicación es que sus cadenas se ordenan como cadenas, y un número ya ha dirigido su atención a la comparación de cadenas de orden natural. Solo agregaré que es un gran ejercicio escribir usted mismo ese comparador, y una gran oportunidad para practicar el desarrollo basado en pruebas. Lo he usado para demostrar TDD en Code Camp; diapositivas y código están here .