Pregunta

Aquí es un simple programa de clasificación de un 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());
}

Yo estaba esperando la salida de este programa como:

1_Update
2_Create
11_Add
12_Delete

Pero cuando ejecuto este programa que estoy recibiendo de salida como:

11_Add
12_Delete
1_Update
2_Create

¿Por qué es esto y cómo puedo obtener el ArrayList para ordenar como se muestra en el resultado esperado?

¿Fue útil?

Solución

Se 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('_')));
    }
});

Otros consejos

Al ordenar este tipo de datos como una cadena, que está comparando los mismos caracteres, incluyendo los dígitos. Todos los de la cadena que comienza con "1", por ejemplo, va a terminar juntos. Por lo que el fin termina similar a este ...

1 10 100 2 20 200

En ningún momento el tipo "darse cuenta" que se va a asignar significado a subconjuntos de la cadena, tales como los números de longitud variable en la parte delantera de la cadena. Al ordenar los números como cadenas, margen a la derecha con ceros tanto como sea necesario para cubrir el número más grande puede ayudar, pero en realidad no resuelve el problema cuando usted no controla los datos, como en el ejemplo. En ese caso, el tipo sería ...

001 002 010 020 100 200

Se clasifica como texto (por orden alfabético), no como números. Para evitar esto se podría aplicar un comparador personalizado como se sugiere en la respuesta por nsayer.

Se está haciendo una comparación lexicográfico. En él se compara el primer carácter de cada cadena ordenándolos. A continuación, compara la segunda cadena de los que tienen la misma primera charater. Cuando se compara el carácter '_' a un número, que es mayor en valor que cualquier carácter único número al igual que 8> 7 y una> 9. Recuerde que está haciendo una comparación carácter y no una comparación numérica.

Hay maneras de implementar su propio enrutamiento de clasificación personalizada que puede ser mejor que cambiar el nombre de nombres de script.

Si cambiar el nombre de nombres de script es una opción, esto puede permitir que otras herramientas de secuencia de comandos que deben utilizarse. Un formato puede ser

01_create_table.sql
02_create_index.sql
11_assign_privileges.sql

Al mantener sus dos primeros dígitos de dos personajes, la comparación lexicográfica va a funcionar.

docs El método Collections.sort () dice:

  

Ordena la lista especificada en   orden ascendente, de acuerdo con la   ordenamiento natural de sus elementos.

Lo que significa para las secuencias que se van a obtener la lista en orden alfabético. El 11_assign_privileges.sql cadena viene antes de la 1_create_table.sql cuerda y 12_07_insert_static_data.sql está antes que 1_create_table.sql etc. Así que el programa está funcionando como se esperaba.

Debido a que las cadenas son ordenados en un orden alfabético y el carácter de subrayado es después de caracteres para los números. Usted tiene que proporcionar un comparador de ejecución "orden natural" para alcanzar el resultado deseado.

La cadena comparar algoritmo de comparación de cada personaje a la vez. 1 tipo antes 2. No importa que es seguido por un 1 o una 2.

Así 100 lo solucionaría antes 2. Si no desea este comportamiento, se necesita un algoritmo de comparación que se encarga de este caso.

Como otros han dicho, los elementos se ordenan alfabéticamente por defecto. La solución es definir una clase concreta java.util.Comparator y pasarlo como un segundo argumento para el método de ordenación. Tu comparador tendrá que analizar los principales números enteros de las cuerdas y compararlas.

Para tener Collection.sort () es un género de forma arbitraria se puede utilizar

Collections.sort(List list, Comparator c)  

A continuación, simplemente implementar un comparador que divide la cadena y ordena basa en primer lugar en el número y luego en el resto o como se desee para ordenar.

Todo el mundo ya ha señalado que la explicación es que las cuerdas están clasificando como cadenas, y varios ya han dirigido su atención al orden natural de comparación de cadenas. Voy a añadir que es un gran ejercicio para escribir que comparador de ti mismo, y una gran oportunidad para practicar desarrollo basado en pruebas. Lo he utilizado para demostrar TDD al Código de Camp; diapositivas y el código son aquí .

Puede añadir la interfaz IComparable y luego ordenar por una propiedad específica. Si usted tiene una colección de artículos de una tienda, por ejemplo, tal vez desee ordenar por precio o por categoría, etc Si usted quiere pedir por su nombre aquí es un ejemplo:

Tenga en cuenta cómo el ArrayList se ordena por la propiedad de nombre de los elementos. Si no se agrega el IComparable continuación, cuando se utiliza el método de clasificación se generará un error.

introducir descripción de la imagen aquí

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

Como se mencionó anteriormente, que busca una aplicación que implementa Comparador una especie natural. Jeff Atwood escribió un excelente de clasificación naturales algún tiempo hace -. vale la pena leer

Si usted está buscando una aplicación Java que he encontrado que éste sea útil: http://www.davekoelle.com/alphanum.html

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top