Java: Ordenar Objetos con Collections.sort() y Comparable

283 palabras 2 minutos Java

Una necesidad frecuente al trabajar con colecciones es ordenar objetos según algún criterio: por nombre, ID, fecha, precio o cualquier otro atributo.

Java proporciona el método sort() junto con la interfaz Comparable para definir el orden natural de una clase.

La interfaz Comparable

Para que una clase pueda ordenarse automáticamente, debe implementar la interfaz Comparable<T> y sobrescribir el método compareTo().

public class Animal implements Comparable<Animal> {

    private int id;
    private String nombre;

    public Animal(int id, String nombre) {
        this.id = id;
        this.nombre = nombre;
    }

    @Override
    public int compareTo(Animal otro) {
        return Integer.compare(this.id, otro.id);
    }
}

El método compareTo() debe devolver:

  • Un valor negativo si el objeto actual es menor.
  • Cero si ambos objetos son equivalentes.
  • Un valor positivo si el objeto actual es mayor.

Ordenando una lista

Una vez implementado Comparable, ordenar una lista es trivial:

ArrayList<Animal> animales = new ArrayList<>();

animales.add(new Animal(3, "Toby"));
animales.add(new Animal(1, "Firulais"));
animales.add(new Animal(2, "Michi"));

Collections.sort(animales);

Resultado:

1 Firulais
2 Michi
3 Toby

La lista queda ordenada según el criterio definido en compareTo().

Ordenar por nombre

También podemos definir el orden natural utilizando otro atributo.

@Override
public int compareTo(Animal otro) {
    return this.nombre.compareTo(otro.nombre);
}

Con este criterio:

Firulais
Michi
Toby

La comparación de cadenas se realiza utilizando el método compareTo() de String.

Orden descendente

Para invertir el orden basta con intercambiar los operandos:

@Override
public int compareTo(Animal otro) {
    return Integer.compare(otro.id, this.id);
}

Resultado:

3 Toby
2 Michi
1 Firulais

Relación entre compareTo() y equals()

Cuando una clase implementa Comparable, es recomendable que exista coherencia entre compareTo() y equals().

Por ejemplo, si dos animales son considerados iguales cuando tienen el mismo ID:

@Override
public boolean equals(Object obj) {
    if (!(obj instanceof Animal))
        return false;

    Animal otro = (Animal) obj;

    return this.id == otro.id;
}

Entonces:

@Override
public int compareTo(Animal otro) {
    return Integer.compare(this.id, otro.id);
}

debería devolver 0 para esos mismos objetos.

Mantener esta consistencia evita comportamientos inesperados en colecciones ordenadas como TreeSet y TreeMap.

¿Qué ocurre internamente?

Cuando se ejecuta:

Collections.sort(animales);

Java llama repetidamente a:

animal1.compareTo(animal2);

para determinar la posición relativa de cada elemento y reordenar la colección.

Conclusión

La interfaz Comparable permite definir el orden natural de una clase mediante el método compareTo(). Una vez implementado, métodos como Collections.sort() pueden ordenar listas de objetos de forma automática y eficiente.

Es una de las herramientas fundamentales para trabajar con colecciones en Java y suele aparecer con frecuencia en entrevistas técnicas, exámenes y aplicaciones reales.