sábado, 11 de febrero de 2012

Comparable en Java

votar
   En la entrada anterior, vimos el uso de Comparator en Java. En ésta nos vamos a centrar en el uso de Comparable. Comparable es una interfaz que sólo contiene un método: compareTo, que nos sirve para ordenar los valores según un orden natural, bien sea numérico o alfabético. Si en Comparator debíamos especificar que tipo de comparación queríamos, y proporcionar un comparator, en este caso vemos que eso no es necesario.

   Lo veremos más claro con un ejemplo, y para eso cogeremos el mismo de la pasada entrada, donde teníamos tres alumnos con sus respectivas notas. Vamos a ordenarlo primero de forma alfabética. Pero antes de nada, un pequeño inciso para principiantes: el método compareTo devuelve un int, que puede ser 1, -1 o 0; da igual que estés comparando nombres. 

   Bien, lo primero que hay que hacer es, por supuesto, implementar la interfaz Comparable, y después sobreescribir el método compareTo, como muestra el ejemplo:

import java.util.*;
public class Alumnos2 implements Comparable <Alumnos2>{//usamos genéricos 
   private int nota;                                                                   
   private String nombre;
   public Alumnos2(int nota, String nombre){//muestra del uso de un constructor
   super( );
   this.nota = nota;
   this.nombre = nombre;
   }
   public void setNota(int nota){//muestra del uso de getters y setters
      this.nota = nota;
   }
   public int getNota( ){
      return nota;
   }
   public void setNombre(String nombre){
      this.nombre = nombre;
   }
   public String getNombre( ){
      return nombre;
   }
   public String toString( ){//adecuamos el resultado de compareTo a nuestras necesidades              
      return String.format("Nombre:%s,  Nota:%s", nombre, nota);
   }
   public int compareTo(Alumnos2 a){
      return nombre.compareTo(a.nombre);
   }
   public static void main(String[ ] args){
      Set <Alumnos2> a = new TreeSet <Alumnos2>( );//añadimos los valores
      a.add(new Alumnos2(8, "Ana"));
      a.add(new Alumnos2(6, "Xose"));
      a.add(new Alumnos2(3, "Carlos"));
      System.out.println(a);
   }
}

   El resultado sería el siguiente:
   [Nombre:Ana, Nota:8, Nombre:Carlos, Nota:3, Nombre:Xose, Nota:6]
   
   Fijaos en el uso del método toString( ). Probad a omitirlo y veréis que el resultado cambia a una serie de extraños números: el hashcode.


 Ya tenemos nuestro ejemplo ordenado alfabéticamente. Pero, ¿y si queremos ordenarlo según las notas de cada alumno?. Entonces lo único que tendremos que hacer es cambiar el método compareTo de la siguiente manera: 


   public int compareTo(Alumnos2 a){
      return this.nota - a.nota;
   }


   De esta forma la salida sería:
 [Nombre:Carlos, Nota:3, Nombre:Xose, Nota:6, Nombre:Ana, Nota:8]


   Si lo que queremos son las notas de mayor a menor, bastaría con hacer esto: 
      return a.nota - this.nota;


   El método compareTo debe seguir un contrato, o "reglas", similares a las del método equals( ), que son las siguientes: 
   Tomando sgn(expresión) donde sgn devuelve -1, 0 o 1, según el valor de la expresión sea negativo, cero o positivo, y con explicaciones para los que no sean de ciencias

  •    sgn(x.compareTo(y)) == -sgn(y.compareTo(x)). Si el primer objeto es menor que el segundo, el segundo debe ser más grande que el primero, y al revés. Y si el primero es igual al segundo, el segundo es igual al primero.
  •    (x.compareTo(y)>0 && y.compareTo(z)>0) implica que x.compareTo(z)>0. Si un objeto es más grande que un segundo objeto, y éste es más grande que un tercero, entonces el primero es más grande que el tercero.
  •    x.compareTo(y) == 0 implica que sgn(x.compareTo(z)) == sgn(y.compareTo(z)). Todos los objetos que son iguales al compararlos deben dar el mismo resultado al compararlos con un tercer objeto.

   Y esto es todo. Si queréis ampliar conocimientos podéis leer el libro de Joshua Bloch "Effective Java". Y no olvidéis visitar nuestra web Java Para Nulos ; )

   

3 comentarios: