Saltar al contenido

Clasificación de una ArrayList de objetos mediante un orden de clasificación personalizado

Te damos la bienvenida a nuestro sitio, ahora vas a encontrar la solucíon que andabas buscando.

Solución:

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

  • Los tutoriales de Java – Colecciones – Orden de objetos

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


Hay varias formas de ordenar un ArrayList. Si quieres definir un natural (defecto) ordenar, entonces necesitas dejar Contact implementar Comparable. Suponiendo que desea ordenar de forma predeterminada en name, luego haga (se omiten las comprobaciones nulas por simplicidad):

public class Contact implements Comparable 

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

    @Override
    public int compareTo(Contact other) 
        return name.compareTo(other.name);
    

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

para que puedas hacer

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

Collections.sort(contacts);

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

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

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

Incluso puedes definir el Comparators en el Contact en sí mismo para que pueda reutilizarlos en lugar de volver a crearlos cada vez:

public class Contact 

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

    // ...

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

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


que se puede utilizar de la siguiente manera:

List contacts = new ArrayList();
// 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 aclarar la parte superior, podría considerar usar un comparador javabean genérico:

public class BeanComparator implements Comparator 

    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) o1).compareTo(o2));
    



que puede utilizar de la siguiente manera:

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

(como ves en el código, posiblemente null los campos ya están cubiertos para evitar NPE durante la clasificación)

Además de lo que ya se publicó debes saber que desde Java 8 podemos acortar nuestro código y escribirlo así:

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

o desde 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 static métodos) se pueden implementar fácilmente usando:

  • lambdas arguments -> body
  • o referencias de métodos source::method.

Ya que Comparator tiene un solo método abstracto int compare(T o1, T o2) es una interfaz funcional.

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

Collections.sort(contacts, new Comparator() 
    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 esta (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 posee static métodos 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 saber sobre la ordenación de colecciones, como ArrayList.

Básicamente necesitas

  • Haz tu Contact clase implementar el Comparable interfaz por
    • creando un método public int compareTo(Contact anotherContact) dentro de ella.
  • Una vez que hagas esto, puedes llamar Collections.sort(myContactList);,
    • donde myContactList es ArrayList (o cualquier otra colección de Contact).

También hay otra forma, que implica la creación de una clase Comparador, y también puede leer sobre eso en la página vinculada.

Ejemplo:

public class Contact implements Comparable 

    ....

    //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;
        
        ...
    

Comentarios y puntuaciones del post

Eres capaz de añadir valor a nuestra información colaborando tu veteranía en las reseñas.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Respuestas a preguntas comunes sobre programacion y tecnología