Pregunta

Estoy buscando para implementar una función de ordenación para mi libreta de direcciones de la aplicación.

Quiero ordenar una ArrayList<Contact> contactArray. Contact es una clase que contiene cuatro campos:nombre, número de casa, número de teléfono móvil y dirección.Quiero ordenar name.

¿Cómo puedo escribir una función de ordenación personalizada para hacer esto?

¿Fue útil?

Solución

Aquí hay un tutorial sobre cómo ordenar objetos:

Aunque daré algunos ejemplos, recomendaría leerlo de todos modos.


Hay varias formas de ordenar un ArrayList. Si desea definir un natural (predeterminado) pedido , entonces debe permitir que Contact implemente Comparable . Suponiendo que desea ordenar por defecto en name, luego haga (se omiten los nullchecks por simplicidad):

public class Contact implements Comparable<Contact> {

    private String name;
    private String phone;
    private Address address;

    public int compareTo(Contact other) {
        return name.compareTo(other.name);
    }

    // Add/generate getters/setters and other boilerplate.
}

para que puedas hacer

List<Contact> contacts = new ArrayList<Contact>();
// Fill it.

Collections.sort(contacts);

Si desea definir un pedido controlable externo (que anula el orden natural), debe crear un Comparator :

List<Contact> contacts = new ArrayList<Contact>();
// Fill it.

// Now sort by address instead of name (default).
Collections.sort(contacts, new Comparator<Contact>() {
    public int compare(Contact one, Contact other) {
        return one.getAddress().compareTo(other.getAddress());
    }
}); 

Incluso puede definir los <=> s en el <=> en sí mismo para poder reutilizarlos en lugar de recrearlos cada vez:

public class Contact {

    private String name;
    private String phone;
    private Address address;

    // ...

    public static Comparator<Contact> COMPARE_BY_PHONE = new Comparator<Contact>() {
        public int compare(Contact one, Contact other) {
            return one.phone.compareTo(other.phone);
        }
    };

    public static Comparator<Contact> COMPARE_BY_ADDRESS = new Comparator<Contact>() {
        public int compare(Contact one, Contact other) {
            return one.address.compareTo(other.address);
        }
    };

}

que se puede usar de la siguiente manera:

List<Contact> contacts = new ArrayList<Contact>();
// Fill it.

// Sort by address.
Collections.sort(contacts, Contact.COMPARE_BY_ADDRESS);

// Sort later by phone.
Collections.sort(contacts, Contact.COMPARE_BY_PHONE);

Y para ponerle crema a la parte superior, podría considerar usar un comparador genérico de javabean :

public class BeanComparator implements Comparator<Object> {

    private String getter;

    public BeanComparator(String field) {
        this.getter = "get" + field.substring(0, 1).toUpperCase() + field.substring(1);
    }

    public int compare(Object o1, Object o2) {
        try {
            if (o1 != null && o2 != null) {
                o1 = o1.getClass().getMethod(getter, new Class[0]).invoke(o1, new Object[0]);
                o2 = o2.getClass().getMethod(getter, new Class[0]).invoke(o2, new Object[0]);
            }
        } catch (Exception e) {
            // If this exception occurs, then it is usually a fault of the developer.
            throw new RuntimeException("Cannot compare " + o1 + " with " + o2 + " on " + getter, e);
        }

        return (o1 == null) ? -1 : ((o2 == null) ? 1 : ((Comparable<Object>) o1).compareTo(o2));
    }

}

que puede usar de la siguiente manera:

// Sort on "phone" field of the Contact bean.
Collections.sort(contacts, new BeanComparator("phone"));

(como puede ver en el código, posiblemente los campos nulos ya están cubiertos para evitar NPE durante la ordenación)

Otros consejos

Además de lo que ya se publicó, debe saber que desde Java 8 podemos acortar nuestro código y escribirlo como:

Collection.sort(yourList, Comparator.comparing(YourClass::getFieldToSortOn));

o como List ahora tiene sort método

yourList.sort(Comparator.comparing(YourClass::getFieldToSortOn));

Explicación:

Desde Java 8, las interfaces funcionales (interfaces con un solo método abstracto; pueden tener más métodos predeterminados o estáticos) se pueden implementar fácilmente usando:

Dado que Comparator<T> tiene solo un método abstracto int compare(T o1, T o2) es la interfaz funcional.

Entonces, en lugar de (ejemplo de @BalusC respuesta )

Collections.sort(contacts, new Comparator<Contact>() {
    public int compare(Contact one, Contact other) {
        return one.getAddress().compareTo(other.getAddress());
    }
}); 

podemos reducir este código a:

Collections.sort(contacts, (Contact one, Contact other) -> {
     return one.getAddress().compareTo(other.getAddress());
});

Podemos simplificar este (o cualquier) lambda omitiendo

  • tipos de argumentos (Java los inferirá en función de la firma del método)
  • o {return ... }

Entonces, en lugar de

(Contact one, Contact other) -> {
     return one.getAddress().compareTo(other.getAddress();
}

podemos escribir

(one, other) -> one.getAddress().compareTo(other.getAddress())

También ahora Comparator tiene métodos estáticos como comparing(FunctionToComparableValue) o comparing(FunctionToValue, ValueComparator) que podríamos usar para crear fácilmente comparadores que deberían comparar algunos valores específicos de los objetos.

En otras palabras, podemos reescribir el código anterior como

Collections.sort(contacts, Comparator.comparing(Contact::getAddress)); 
//assuming that Address implements Comparable (provides default order).

Esta página le dice todo lo que necesita para saber cómo ordenar colecciones, como ArrayList.

Básicamente necesitas

  • haga que su clase Contact implemente la interfaz Comparable
    • creando un método public int compareTo(Contact anotherContact) dentro de él.
  • Una vez que hagas esto, puedes llamar a Collections.sort(myContactList);,
    • donde myContactList es ArrayList<Contact> (o cualquier otra colección de <=>).

También hay otra forma, que implica crear una clase Comparator, y también puedes leer sobre eso desde la página vinculada.

Ejemplo:

public class Contact implements Comparable<Contact> {

    ....

    //return -1 for less than, 0 for equals, and 1 for more than
    public compareTo(Contact anotherContact) {
        int result = 0;
        result = getName().compareTo(anotherContact.getName());
        if (result != 0)
        {
            return result;
        }
        result = getNunmber().compareTo(anotherContact.getNumber());
        if (result != 0)
        {
            return result;
        }
        ...
    }
}

BalusC y bguiz ya han dado respuestas muy completas sobre cómo usar los comparadores integrados de Java.

Solo quiero agregar que google-collections tiene una Clase de pedido que es más " poderoso " que los comparadores estándar. Puede valer la pena echarle un vistazo. Puede hacer cosas interesantes, como ordenar los compuestos, revertirlos, ordenar según el resultado de una función para sus objetos ...

Aquí es una publicación de blog que menciona algunos de sus beneficios.

Debe hacer que sus clases de contacto implementen Comparable y luego implementa el método compareTo(Contact). De esa manera, Collections.sort podrá ordenarlos por usted. Según la página a la que me vinculé, compareTo 'devuelve un entero negativo, cero o un entero positivo ya que este objeto es menor, igual o mayor que el objeto especificado.'

Por ejemplo, si desea ordenar por nombre (de la A a la Z), su clase se vería así:

public class Contact implements Comparable<Contact> {

    private String name;

    // all the other attributes and methods

    public compareTo(Contact other) {
        return this.name.compareTo(other.name);
    }
}

Al usar lambdaj puede ordenar una colección de sus contactos (por ejemplo, por sus nombre) como sigue

sort(contacts, on(Contact.class).getName());

o por su dirección:

sort(contacts, on(Contacts.class).getAddress());

y así sucesivamente. Más en general, ofrece un DSL para acceder y manipular sus colecciones de muchas maneras, como filtrar o agrupar sus contactos en función de algunas condiciones, agregar algunos de sus valores de propiedad, etc.

El Collections.sort es una buena implementación de clasificación. Si no tiene The comparable implementado para Contact, deberá pasar un Implementación del comparador

De nota:

  

El algoritmo de ordenación es un mergesort modificado (en el que la fusión se omite si el elemento más alto en la sublista baja es menor que el elemento más bajo en la sublista alta). Este algoritmo ofrece un rendimiento garantizado de n log (n). La lista especificada debe ser modificable, pero no necesita ser redimensionable. Esta implementación volca la lista especificada en una matriz, ordena la matriz e itera sobre la lista restableciendo cada elemento desde la posición correspondiente en la matriz. Esto evita el rendimiento de n2 log (n) que resultaría de intentar ordenar una lista vinculada en su lugar.

El orden de fusión es probablemente mejor que la mayoría de los algoritmos de búsqueda que puede hacer.

Lo hice de la siguiente manera. número y nombre son dos arraylist. Tengo que ordenar el nombre. Si se produce algún cambio en el nombre del orden arralista, la lista de números también cambia su orden.

public void sortval(){

        String tempname="",tempnum="";

         if (name.size()>1) // check if the number of orders is larger than 1
            {
                for (int x=0; x<name.size(); x++) // bubble sort outer loop
                {
                    for (int i=0; i < name.size()-x-1; i++) {
                        if (name.get(i).compareTo(name.get(i+1)) > 0)
                        {

                            tempname = name.get(i);

                            tempnum=number.get(i);


                           name.set(i,name.get(i+1) );
                           name.set(i+1, tempname);

                            number.set(i,number.get(i+1) );
                            number.set(i+1, tempnum);


                        }
                    }
                }
            }



}

el uso de este método:

private ArrayList<myClass> sortList(ArrayList<myClass> list) {
    if (list != null && list.size() > 1) {
        Collections.sort(list, new Comparator<myClass>() {
            public int compare(myClass o1, myClass o2) {
                if (o1.getsortnumber() == o2.getsortnumber()) return 0;
                return o1.getsortnumber() < o2.getsortnumber() ? 1 : -1;
            }
        });
    }
    return list;
}

`

y uso: mySortedlist = sortList(myList); No hay necesidad de implementar comparador de su clase.Si desea que el orden inverso de intercambio 1 y -1

Debería usar la función Arrays.sort. Las clases que contienen deben implementar Comparable.

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