Beruflich Dokumente
Kultur Dokumente
Versin: 0.0.5
2.
3.
El tipo Comparable...................................................................................................................................... 5
4.
5.
6.
Ejercicios.................................................................................................................................................... 10
o
Criterio de Igualdad: detalles
Introduccin a la Programacin
En el esquema anterior el criterio de igualdad y la representacin como cadena estn relacionados con el
tipo Object, mientras que el orden natural est relacionado con el tipo Comparable, y el orden alternativo
con el tipo Comparator. Estos tipos los veremos con ms detalles en los siguientes apartados.
2. El tipo Object
En Java existe una clase especial llamada Object. Todas las clases que definamos y las ya definidas heredan
de Object, es decir, implcitamente Object es un tipo al que extienden todas las clases Java. Como cualquier
tipo, Object proporciona una serie de mtodos pblicos, no static. Aunque tiene ms mtodos, en este Tema
nos vamos a centrar solamente en tres de esos mtodos: equals, hashCode y toString. Veremos sus
propiedades, las restricciones entre ellos y la forma de redisearlos para que se ajusten a nuestras
necesidades. La signatura de estos mtodos es1:
boolean equals(Object o);
int hashCode();
String toString();
Como el tipo Object es ofrecido por todos los objetos que creemos, los mtodos anteriores estn disponibles
en todos los objetos, es decir, todos los objetos heredan los mtodos equals, hashCode y toString de la clase
Object. Estos mtodos tienen definido un comportamiento por defecto. Veamos para qu se utilizan cada
uno de estos mtodos:
El mtodo equals(Object o) se utiliza para decidir si el objeto es igual al que se le pasa como parmetro.
Recordemos que para decidir si dos objetos son idnticos se usa el operador ==.
El mtodo hashCode() devuelve un entero, que es el cdigo hash del objeto. Todo objeto tiene, por lo
tanto, un cdigo hash asociado.
El mtodo toString() devuelve una cadena de texto que es la representacin exterior del objeto. Cuando
el objeto se muestre en la consola tendr el formato indicado por su mtodo toString correspondiente.
Todos los objetos ofrecen estos tres mtodos. Por lo tanto es necesaria una buena comprensin de sus
propiedades y un buen diseo de los mismos.
Propiedades y restricciones.
Propiedades de equals:
Reflexiva: Un objeto es igual a s mismo. Es decir, para cualquier objeto x, distinto de null, se debe
cumplir que x.equals(x) es true y x.equals(null) es false.
3. Diseo de Tipos I
Simtrica: Si un objeto es igual a otro, el segundo tambin es igual al primero. Es decir, para dos objetos
cualesquiera x e y, distintos de null, se debe cumplir que x.equals(y) => y.equals(x). Mltiples
invocaciones de x.equals(y) deben devolver el mismo resultado si el estado de x e y no ha cambiado.
Transitiva: Si un objeto es igual a otro, y este segundo es igual a un tercero, el primero tambin ser
igual al tercero. Es decir para tres objetos x, y, z, distintos de null, se debe cumplir que x.equals(y)&&
y.equals(z) => x.equals(z).
Propiedades de equals/toString:
Si dos objetos son iguales, sus representaciones en forma de cadena tambin deben serlo. Es decir, para
dos objetos cualsequiera x e y, distintos de null, se debe cumplir que x.equals(y) =>
x.toString().equals(y.toString()).
Propiedades de equals/hashCode:
Si dos objetos son iguales, sus cdigos hash tienen que coincidir. La inversa no tiene por qu ser cierta.
Es decir, para dos objetos cualesquiera x e y, distintos de null, se debe cumplir que x.equals(y) =>
x.hashCode() == y.hashCode(). Sin embargo, no se exige que dos objetos no iguales produzcan cdigos
hash desiguales, aunque hay que ser consciente de que se puede ganar mucho en eficiencia si en la
mayora de los casos objetos distintos tienen cdigos hash distintos.
Las propiedades y restricciones anteriores son muy importantes. Si no se cumplen, el programa que
diseemos puede que no funcione adecuadamente. Todos los tipos ofrecidos en la API de Java tienen un
diseo adecuado de esos tres mtodos. Pero recordemos que esos tres mtodos estn slo disponibles en
los tipos que extienden Object. Es decir, en los tipos que definen objetos y no estn disponibles en los tipos
primitivos. Por lo tanto, esos mtodos ya estn disponibles en Integer, Long, Float, Double y String, pero no
en los tipos int, long, float y double.
Veamos un ejemplo con la implementacin en el tipo Punto del tema 1, el esquema de diseo del tipo, ahora
sera:
Tipo Punto
Propiedades:
o Coordenada X: Double, consultable y modificable.
o Coordenada Y: Double, consultable y modificable.
Otras operaciones:
o distanciaAOtroPunto (Double p): Double, devuelve la distancia del punto que invoca al mtodo
al punto p.
Representacin como cadena: (coordenadaX, coordenadaY)
Criterio de igualdad: Dos puntos son iguales si sus coordenadas X son iguales y sus coordenadas Y son
iguales.
Teniendo la descripcin anterior del tipo Punto, los mtodos toString, equals y hashCode que deberan
incluirse en la clase PuntoImpl son los siguientes:
Introduccin a la Programacin
Veamos con un poco de ms detalle el cdigo anterior, del que comentaremos algunos detalles:
Podemos estar seguros que el casting a Punto no disparar excepciones puesto que se hace
despus de comprobar que objeto ofrece ese tipo. Evidentemente si p no es de tipo Punto el
resultado es false.
Hemos supuesto que sus propiedades no pueden tomar el valor null. Si esto no fuera as, se
disparara una excepcin en getX().equals(p1.getX()) puesto que se intentara invocar el
mtodo equals sobre un objeto null. Eclipse proporciona de forma automtica un cdigo ms
completo que tiene en cuenta la posibilidad de que el objeto a comparar, o algunos de los
atributos que participan en la igualdad, sean null.
La cadena resultante en el mtodo toString se debe calcular a partir de los resultados devueltos
por los correspondientes toString de las propiedades involucradas en la igualdad y,
posiblemente, otras propiedades derivadas de las mismas.
En este caso no es necesario invocar el mtodo toString porque cuando un tipo objeto est
dentro de una operacin con otros operandos de tipo String el compilador llama
automticamente al mtodo. Es decir, en ese contexto el compilador convierte
automticamente el tipo dado a String.
3. Diseo de Tipos I
adecuadamente. Es decir, que los hashCode de dos objetos distintos sean en la mayora de los
casos distintos.
Un ejemplo de invocacin a equals es el que se muestra a continuacin:
Ejemplo 2. Ejemplo de invocacin de equals
3. El tipo Comparable
El tipo Comparable un orden a los objetos de un tipo creado por el usuario, al que llamaremos orden
natural. Java ya proporciona un orden natural a los tipos envoltorio como Integer y Double o al tipo
inmutable String (que extienden a Comparable) permitiendo que, por ejemplo, se puedan ordenar cuando
estn sobre una Lista o array.
El tipo Comparable est definido como2:
package java.lang;
public interface Comparable<T>{
int compareTo(T o);
}
El tipo Comparable est incluido en el paquete java.lang de Java y se compone de un slo mtodo: el
mtodo compareTo. El tipo Comparable usa tipos genricos y sirven para una relacin de orden total sobre
los objetos de un tipo dado. El tipo Comparable sirve para establecer el orden natural de un tipo dado, y su
implementacin tiene que cumplir una serie de restricciones:
El mtodo compareTo debe disparar la excepcin NullPointerException cuando toma como parmetro un
valor null.
compareTo compara dos objetos this y p2 y devuelve un entero que es:
Negativo si this es menor que p2
Introduccin a la Programacin
En general, para implementar el mtodo compareTo usaremos los mtodos compareTo de las propiedades
involucradas en la igualdad o algunas otras derivadas. Un orden natural adecuado puede ser comparar en
primer lugar por una propiedad elegida arbitrariamente, si resulta cero comparar por la segunda propiedad,
etc. Veamos un ejemplo, definiendo el tipo Persona con el esquema de diseo de tipos usado en este tema.
Tipo Persona
Propiedades:
o DNI: String, consultable.
o Nombre: String, consultable y modificable.
o Apellidos: String, consultable y modificable.
Representacin como cadena: apellidos, nombre (dni)
Criterio de igualdad: Dos personas son iguales si sus dnis son iguales, sus apellidos son iguales y sus
nombres.
Criterio de ordenacin natural: Por apellidos, nombre y DNI.
Lo primero que debemos modificar respecto al esquema de diseo de tipos del tema 1 es su interfaz, ya que
al tener definido el tipo un orden natural tiene que extender a Comparable):
Ejemplo 3. Diseo de la interfaz Persona extendiendo a Comparable
Los mtodos que habra que aadir a la clase PersonaImpl seran los relacionados con Object, y compareTo.
Ejemplo 4. Mtodos toString, equals, hashCode y compareTo en PersonaImpl
3. Diseo de Tipos I
}
return r;
}
public int hashCode(){
return getDNI().hashCode()+ getApellidos().hashCode()*1+
getNombre().hashCode()*31*31;
}
public int compareTo(Persona p) {
int r;
if(p==null){
throw new NullPointerException();
}
r = getApellidos().compareTo(p.getApellidos());
if (r == 0) {
r = getNombre().compareTo(p.getNombree());
if (r == 0){
r = getDNI().compareTo(p.getDNI());
}
}
return r;
}
Note que el orden natural para el tipo Persona deber ser compatible con equals y, por tanto, deber tener
en cuenta las mismas propiedades escogidas para definir el criterio de igualdad.
Un ejemplo de uso del mtodo compareTo es el siguiente:
Ejemplo 5. Ejemplo de uso del mtodo compareTo
4. El tipo Comparator
El Comparator tambin sirve para proporcionar un orden a los objetos de un tipo creado por el usuario, y
sirve para definir un criterio de ordenacin alternativo al proporcionado por el criterio de ordenacin
natural. El tipo Comparator est incluido en el paquete java.util y, aunque tiene un mtodo equals,
solamente usaremos el mtodo compare. Su definicin es la siguiente3:
Introduccin a la Programacin
package java.util;
public interface Comparator<T>{
int compare(T o1, T o2);
El tipo Comparator tambin usa tipos genricos y tambin define, al igual que Comparable, una relacin de
orden total. El mtodo compare compara los dos objetos que toma como parmetro y su implementacin
tiene que cumplir los siguientes requisitos:
Esta recomendacin tiene el problema de que si hacemos un Comparator coherente con equals y ste debe
ser coherente con compareTo.
Un criterio de ordenacin alternativo para Persona puede ser ordenar primero por DNI, luego por apellidos,
y luego por nombre. Un comparador para especificar este criterio de ordenacin alternativo es:
Ejemplo 6. Criterio de ordenacin alternativo para Persona.
import java.util.Comparator;
public class ComparadorPersonaDNI implements Comparator<Persona> {
public int compare(Persona p1, Persona p2){
int r;
r = p1.getDNI().compareTo(p2.getDNI());
if (r ==0 ){
r= p1.getApellidos().compareTo(p2.getApellidos());
if (r == 0){
r=p1.getNombre().compareTo(p2.getNombre());
}
}
return r;
}
}
3. Diseo de Tipos I
Si quisiramos definir un criterio de ordenacin alternativo para ordenar las personas exclusivamente por su
nombre, tendramos un comparador que no es consistente con la igualdad. En este caso, si queremos
conseguir la consistencia con equals (es decir, que si el comparador devuelve cero, equals devuelve true)
hacemos una comparacin adicional, aunque la definamos explcitamente en el criterio de ordenacin
alternativo. Esta comparacin se har si los objetos son iguales segn el criterio de ordenacin alternativo.
En este caso se desempata con el orden natural del tipo. Con esto conseguimos, al menos que si compare da
cero entonces equals es true. As un comparador para ordenar las personas por su nombre sera:
Ejemplo 8. Comparador con desempate usando el orden natural.
import java.util.Comparator;
public class ComparadorPersonaNombre implements Comparator<Persona> {
public int compare(Persona p1, Persona p2){
int r;
r = p1.getNombre().compareTo(p2.getNombre());
if (r ==0 ){
r= p1.compareTo(p2);
}
return r;
}
}
Note que esta solucin del desempate con compareTo solamente es posible si el tipo tiene definido un
orden natural.
10
Introduccin a la Programacin
public
public
public
public
public
public
public
public
public
public
static
static
static
static
static
static
static
static
static
static
Note que hay dos versiones del mtodo sort: una que no tiene un comparador como argumento, y que, por
lo tanto, ordena por el criterio de ordenacin natural, y otra, con un comparador, que ordena segn un
criterio de ordenacin alternativo.
6. Ejercicios
1. Ample el tipo Libro definido en el Tema 1, para que tenga en cuenta las siguientes propiedades y
criterios, y sabiendo que ahora el tipo es Comparable.
Propiedades:
o ISBN, de tipo cadena, consultable. Debe tener obligatoriamente 0, 10 13 caracteres
o Ttulo, de tipo cadena, consultable y modificable.
o Autor, de tipo Persona, consultable y modificable.
o Nmero de pginas, de tipo entero, consultable y modificable. Debe ser mayor que cero.
o Precio, de tipo real, consultable y modificable. Debe ser mayor o igual que cero.
o Es best-seller, de tipo booleano, consultable y modificable.
3. Diseo de Tipos I
2. Tipo Rectangulo
Propiedades:
o Lado A: Double, consultable y modificable. Debe ser mayor o igual que cero.
o Lado B: Double, consultable y modificable. Debe ser mayor o igual que cero.
o Centro: Punto, consultable y modificable
o Angulo con Eje X: Double, consultable y modificable
o Area : Double, consultable, derivada, se calcula como el producto de los lados.
Representacin como cadena: lados, centro y ngulo separados por comas y entre llaves
Criterio de igualdad: Dos rectngulos son iguales si tienen los mismos lados, centro y ngulo
Criterio de ordenacin natural: No tiene.
Orden alternativo: rea.
11