jueves, 3 de febrero de 2011

Ordenamiento de colecciones con interface Comparable

Una de las interfaces más útiles en aspectos de ordenar colecciones es la interface Comparable. Al usar esta interface en una clase podemos disponer de la clase de utilidades "Collections" para ordenar de alguna forma deseada, cualquier colección que contenga objetos de ese tipo. En el siguiente ejemplo se utiliza una lista de personas que se ordenan por edad. Para ello solo se implementa el método "compareTo" (preferiblemente usando "generics") en el cual solo se resta la edad de los dos objetos comparados. Después es solo cuestión de invocar el método Collections.sort(Collection<object>).


import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

public class Person implements Comparable<Person>{

protected String name;
protected int age;

public Person(String name, int age) {
this.name=name;
this.age=age;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

/**
* Implementing comparison by age.
*/
public int compareTo(Person o) {
return this.age - o.getAge();
}

@Override
public String toString() {
return this.name + ":" + this.age;
}

public static void main(String[] args) {
List<Person> myFamily = new LinkedList<Person>();
myFamily.add(new Person("Gabriel", 28));
myFamily.add(new Person("Yamai", 51));
myFamily.add(new Person("Blanca", 25));
myFamily.add(new Person("Daniel", 12));
myFamily.add(new Person("Daniela", 27));
myFamily.add(new Person("Lydia", 17));

/*Let's sort the collection.*/
Collections.sort(myFamily);

for(Person familiyMember : myFamily) {
System.out.println(familiyMember);
}
}
}


Salida:

Daniel:12
Lydia:17
Blanca:25
Daniela:27
Gabriel:28
Yamai:51

Así que olvidemonos de hacer ordenamientos de burbuja ;).


7 comentarios:

  1. Un de los detalles muy interesante, es que le podes pasar al sort, un comparator, el mismo puede ser bastante tonto como por ejemplo, el comparator puede recibir simplemente un parametro DES o ASC
    Dependiendo del parametro, invoca al comparator del objeto mismo y lo multiplica por 1 o por -1, asi podes ordenas ascendente o descendente sin modificar tu logica, de igual manera podrias usar otros criterios de orden basados en el criterio sort propio del objeto.

    ResponderEliminar
  2. Hola y cómo se haría, si además de la edad tenemos que comparar por nombre?, es decir, suponiendo que dos personas tienen 12 años, ordenar por la edad y después por el nombre y peor aun suponiendo que también por apellido en el caso de que se llamen igual y tengan la misma edad

    ResponderEliminar
    Respuestas
    1. Una manera, no creo que la más óptima, es concatenar todos los valores que se toman en cuenta en la comparación como un solo String, y utilizar la implementación de compareTo de la clase String.
      Pero con un poco de cabeza se pueden encontrar maneras alternativas de hacerlo.

      Eliminar
  3. Hola un consulta, que patron de diseño estaria usando internamente, la interfaz comparable y comparator?

    ResponderEliminar
  4. Saludos Renzo!

    No es un patrón en sí mismo. La implementación del método "compareTo" es la clave para utilizar las librerías de Collections para el ordenamiento.

    ResponderEliminar
  5. no entiendo muy bn el pedazo del compareto por que se restan las edades en el return ?

    ResponderEliminar
    Respuestas
    1. El método "compareTo" retorna en todos los casos un entero. Si es 0 significa que los dos objetos comparados son iguales, si retorna mayor a 0 significa que el que se compara es mayor, y si retorna menor a 0 es porque es menor. Al restar las edades generamos ese rango de -n a n. Espero aclare un poco más.

      Eliminar