Minitip: Ordenación de vectores de datos complejos

Con la cantidad de veces que uno tiene que ordenar vectores en una aplicación, no me extrañó nada encontrar que la ordenación de colecciones estaba en la api de java. Porque si cada vez que te pongas con una aplicación vas a tener que hacer una clase con algoritmos de ordenación para los elementos con los que trabajes, pues oye, no es mala idea hacerlo genérico y meterlo en el conjunto de instrucciones de java, ¿que no?

obviously

La clase java.util.Collections consiste solamente en procedimientos estáticos que operan y/o devuelven colecciones de objetos. Podeis mirar la documentación de la clase en el api de java si queréis saber cuales son todos esos métodos, pero yo me voy a centrar en Collections.sort.

public static <T extends Comparable<? super T>> void sort(List<T> list)

Sort ordena la colección pasada como parámetro en orden ascendente, de acuerdo al “orden natural” de sus elementos. Esto hace que la colección que se quiera ordenar tenga que cumplir dos cosas: Sus elementos deben ser ordenables (implementar el interfaz Comparable), y deben ser comparables “entre sí” (de la misma clase).

Otra declaración del método acepta un segundo argumento, que es el orden en el que se quieran ordenar los elementos (si es null el orden será el natural de los elementos).

public static <T> void sort(List<T> list, Comparator<? super T> c)

Lo bonito de este Collections.sort es que puedes usarlo con colecciones de objetos complejos. No me refiero a que no tengan que ser tipos primitivos, cosa que ya habréis deducido porque como dice la misma definición del método, con que implementen Comparator ya vale. Es que si tienes algo como esto:

class MiTipoAbstractoDeDatos {
String nombre;
int grados;
date fecha;
List<Integer> mediciones;
List<otroTad>vectorConCosas;
/*constructor, accesores y mutadores */
}

Y haces:

List<MiTipoAbstractoDeDatos > vectorTad = new ArrayList()<MiTipoAbstractoDeDatos >;
//añadimos cosas al vector
Collections.sort(vectorTad );

Se lo come.

Eat all the Arrays!
Eat all the Arrays!

Y tras ejecutarse, vectorTad tendrá sus elementos ordenados.

Ahora bien, ¿ordenados según qué? Porque ayer me encontré esa instrucción en el código de la aplicación cuando miraba cómo solucionar la incidencia “los elementos no se están ordenando como deben”.

No sé qué hace el sort para tipos de datos complejos, pero si tenéis que usarlo y el vector devuelto no está ordenado por el campo que necesitáis (pongamos, un vector de tablas de datos ordenado por el nombre de empresa, pero el sort os lo ordena por fecha de alta en la seguridad social), la solución es tan sencilla como redefinir el método compare del tipo Collections.

Supongamos que tenemos un vector de elementos de un tipo complejo de datos:

TipoComplejo tipoComplejo;
List<TipoComplejo> vectorComplejo = new ArrayList()<TipoComplejo>;

Se quiere ordenar el vector según la propiedad “indice”, que es de tipo String. Redefiniremos el método compare de la clase Collections para que compare – y según la ordenación que a nosotros nos interese – el elemento por el que queremos que se ordene la colección.

Solo tendremos que poner el código tal que así cuando hagamos la llamada a Collections.sort:

Collections.sort(vectorComplejo, new Comparator<TipoComplejo>(){
public int compare(TipoComplejo o1, TipoComplejo o2){
String indice1 = o1.getIndice();
String indice2 = o2.getIndice();
if(indice1.equals(indice2))
return 0;
return indice1.compareTo(indice2);
}
}); 

Por si acaso: compare devuelve -1 si el primer argumento es menor que el segundo, 0 si son iguales, y 1 si el primer argumento es mayor que el segundo (y ya se implementa ese comportamiento de la forma que nos interese).

Y ya está, ya tienes el vector ordenado según el campo que quieras y el orden (ascendente o descendente) que necesites 😀

success_baby

Espero que este post pueda resultar de utilidad. Y si no lo ha sido, aquí tenéis un gato para compensar por las molestias ^^

conspiracy-cat-meme

One thought on “Minitip: Ordenación de vectores de datos complejos

Deja una respuesta

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

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.