domingo, 14 de noviembre de 2010

Cambiando el orden natural de las cosas (Powered by Java)

Diferencia entre Comparable y Comparator

La diferencia principal entre Comparable y Comparator es que Comparable es utilizado para implementar el orden natural, sin necesidad de especificar un Comparator, por ejemplo, los String son comparados alfabéticamente. Usamos Comparator cuando queramos crear otro tipo de orden que no sea el natural.

El contrato que implica implementar Comparable requiere de un parámetro extra, el objeto con el que comparar compareTo(obj1) de forma que la comparación se realizará del objeto en si (this) con el objeto pasado como parámetro. Comparator, sin embargo obliga a implementar el método compare (obj1, obj2) de forma que los dos objetos a comparar son pasado como parámetro y el objeto que implementa el método compare simplemente sirve de apoyo a la comparación.
Sobreescritura de los métodos compareTo y compare

La forma de sobreescribir estos métodos es muy similar al equals. Los dos métodos cumplen las mismas restricciones que podemos objtener del API de Java:

* Devolvemos un número negativo si el objeto es menor, devolvemos un cero si es igual y un número positivo si el objeto es mayor.
* Comparamos el objeto con otro objeto del mismo tipo. Si no son del mismo tipo, lanzamos un ClassCastException.

La notación sgn(expresion) es la función matemática signum, la cual devuelve -1,0, o 1 según sea negativo, zero o positivo

* Debemos asegurar que:

sgn(compare(x,y)) == -sgn(compare(x,y)), para todo x, y.

Esto implica que compare(x,y)) lanzará una excepción sii compare(x,y) también la lanza.

* Debemos asegurar que la relación es transitiva:

compare(x,y) > 0 && compare(y,z) > 0 implica que compare(x,z) > 0

* Debemos asegurar que:

compare(x,y) == 0 implica que

sgn(compare(x,z)) == sgn(compare(y,z)), para todo z.

* Se recomienda, aunque no es estrictamente neceario, nos puede evitar poblemas al usar colecciones que implementen esta interfaz.

(compare(x,y) == 0) == (x.equals(y))

* El orden natural para una clase “c” tiene que ser consistente con el equals si y solo sí:

compare(e1,e2) == 0 tiene que ser el mismo resultado que

para e1.equals(e2) para cada e1 y e2 de la clase “c”.
Uso de Comparable y Comparator

Podemos usarlos en listas y arrays mediante los métodos Collections.sort y Arrays.sort.También como claves en un mapa ordenado TreeMap o como elementos en un set ordenado TreeSet.

En el caso de Comparable los objetos tienen que implementar esta interfaz para que los ordene automáticamente. Para el caso del Comparator debemos especificar el Comparator.
Ejemplos

01 //Ejemplo Comparable
02 public class Person implements Comparable {
03 private String firstName;
04 private String lastName;
05
06 public Person(String firstName, String lastName) {
07 if (firstName == null || lastName == null)
08 throw new NullPointerException();
09 this.firstName = firstName;
10 this.lastName = lastName;
11 }
12
13 @Override
14 public String toString() {
15 return String.format("%s, %s", firstName, lastName);
16 }
17
18 @Override
19 public int compareTo(Person p) {
20 int lastCmp = firstName.compareTo(p.firstName);
21 return (lastCmp != 0 ? lastCmp : lastName.compareTo(p.lastName));
22 }
23
24 public static void main(String[] args) {
25 Set p = new TreeSet();
26 p.add(new Person("Ana", "Rodes"));
27 p.add(new Person("Hector", "Lopez"));
28 p.add(new Person("Ana", "Buigues"));
29 p.add(new Person("Carlitos", "Perez"));
30
31 for (Person person : p)
32 System.out.println(person);
33 }
34 }

La salida será:

01 //Ejemplo Comparator
02 public class LengthComparator implements Comparator {
03 @Override
04 public int compare(Person t1, Person t2) {
05 if (t1.toString().length() > t2.toString().length())
06 return 1;
07 else if (t1.toString().length() < t2.toString().length())
08 return -1;
09 else
10 return 0;
11 }
12
13 public static void main(String[] args) {
14 List p = new ArrayList();
15 p.add(new Person("Ana", "Rodes"));
16 p.add(new Person("Hector", "Lopez"));
17 p.add(new Person("Ana", "Buigues"));
18 p.add(new Person("Carlitos", "Perez"));
19 Collections.sort(p, new LengthComparator());
20
21 for (Person person : p)
22 System.out.println(person);
23 }
24 }

0 comentarios:

Publicar un comentario