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
/Comparator
es una interfaz mientras queequals
es 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 conComparable
implementada tienen lo que se llama un orden natural con el que ordenarse por defecto. Comparable/Comparator
admiten 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:
Comparable
necesita 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).Comparator
necesita implementar el métodocompare(T o1, T o2)
como miembro del objeto comparador que se encargará de compararo1
cono2
: el comparador es un objeto independiente que no tiene relación cono1
nio2
.
- Para qué:
Comparable
va a establecer un orden natural para el tipo mientras queComparator
se 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
o1
es 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
Comparator
es 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