equals es un miembro de Object. Sirve para comparar dos objetos y obtener si son iguales/equivalentes.Por otra parte existen las interfaces
Comparable y Comparator que sirven también para comparar dos objetos, pero las usaremos para ordenar pues nos pueden decir cuan iguales/distintos son dos objetos midiéndolo con un entero (int). Las diferencias entre estas dos formas de comparar las podemos resumir en:Comparable/Comparatores una interfaz mientras queequalses un miembro de todos los objetos (todos tienen una implementación).- Todos los objetos pueden comparar su igualdad (usar
equals), pero sólo los objetos conComparableimplementada tienen lo que se llama un orden natural con el que ordenarse por defecto. Comparable/Comparatoradmiten un tipo variableT(el tipo que pueden comparar). La definición de este tipo variable afectara al parámetro de su único método a implementar:compareTo(T o)/compare(T o1, T o2).
Comparable y Comparator es el dónde y el para qué de su funcionalidad:- Dónde:
Comparablenecesita implementar el métodocompareTo(T o)como miembro del objeto que se va a comparar con el parámetroo, y son del mismo tipoT(teniendo en cuenta que los subtipos son del tipo de su supertipo).Comparatornecesita implementar el métodocompare(T o1, T o2)como miembro del objeto comparador que se encargará de compararo1cono2: el comparador es un objeto independiente que no tiene relación cono1nio2.
- Para qué:
Comparableva a establecer un orden natural para el tipo mientras queComparatorse puede usar para hacer una ordenación puntual, pudiendo tener varios comparadores para ordenar por distintos criterios.
equals nos dice si dos valores son iguales, Comparable/Comparator nos dice cuan iguales son y nos permite ordenar
¿Cómo funcionan?
El único método que debe implementar cada una debe devolvernos:
- un número negativo si
o1es menor queo2, - cero si son iguales (no implica que
o1.equals(o2)seatrue) o - positivo si es mayor.
equals que devuelve un boolean.Se recomienda encarecidamente que ambos métodos sean coherentes entendido como:
o1.compareTo(o2)/compare(o1, o2) == 0 debería dar el mismo resultado que o1.equals(o2).¿Cuándo usamos cada una?
Desde mi experiencia yo tiendo a generar comparadores antes que a implementarComparable. Mis motivos son:- Puedo ordenar un tipo incluso si no tengo acceso al código para implementar
Comparable - Puedo disponer de varios comparadores como constantes (
static final) en un tipo para poder ordenarlos fácilmente, mientras que sólo puedo tener una implementación paraComparable Comparatores una interfaz funcional y puedes instanciarlos con lambdas desde Java 8. El código queda muy legible y compacto con lo que no es un problema crearlos como antiguamente que había que hacer un tipo sólo para eso.
Sólo se puede implementar
Comparable una vez, si un supertipo ya lo tiene implementado habrá que sobrescribir el método compareTo si debe ser distinta implementación y las comparaciones dos-a-dos podrían salir inconsistentes (ver type erasure cuando se hable de genéricos).El consejo definitivo es: haz un comparador a menos que el diseño de un código en concreto te obligue a implementar
Comparable (por ejemplo que tenga que usarse el tipo como clave de un mapa ordenado o que un tipo genérico imponga la interface Comparable).
Si no estás obligado a usar
Comparable mejor hazte un Comparator para tener el código de ordenamiento separadoPara ver el uso de Comparator termino la entrada añadiendo éste código al de la entrada anterior que ordena los vehículos por su color:
System.out.println("\nLista ordenada (por color):");
vehiculos.sort((v1, v2) -> v1.getColor().compareTo(v2.getColor()));
vehiculos.forEach(System.out::println);
Así queda más limpio y separado el código de vehículos y el de ordenación para un caso concreto. Si te fijas en los métodos de Comparator verás cómo han potenciado la interfaz desde Java 8 y lo fácil que es tener un comparador que ordene por orden inverso, usando una clave específica (Comparable) o que trate los valores null de forma distinta. Todo son facilidades.
No hay comentarios:
Publicar un comentario