Mostrando las entradas con la etiqueta comparable. Mostrar todas las entradas
Mostrando las entradas con la etiqueta comparable. Mostrar todas las entradas

jueves, 28 de abril de 2011

Implementación la funcion compareTo de Comparable en java





La interface Comparable se emplea, para indicar si el objeto representado por this es menor, igual o mayor que el objeto que se pasa como parametro. A continuacion se presentan 3 ejemplos de clases que definen la funcion compareTo en base a una propiedad existente. Nota, en algunos paises existe el concepto de National Identification Number (CURP en México, RUN en Chile, DNI en España y Argentina o Tarjeta de Identidad en colombia, por ejemplo)


public class ExamplePerson1 implements Comparable<ExamplePerson1> {

 private String nin; // National Identification Number
 private String name;
 private String surname;

 ...

 @Override
 public int compareTo(ExamplePerson1 o) {
  return this.nin.compareTo(o.nin);
 }

}

public class ExamplePerson2 implements Comparable<ExamplePerson2> {

 private Integer id;
 private String name;
 private String surname;

 ...

 @Override
 public int compareTo(ExamplePerson2 o) {
  return this.id.compareTo(o.id);
 }

}

public class ExamplePerson3 implements Comparable<ExamplePerson3> {

 private int id;
 private String name;
 private String surname;

 ...

 @Override
 public int compareTo(ExamplePerson3 o) {
  return this.id < o.id ? -1 : (this.id == o.id ? 0 : 1);
 }

}

En el ejemplo 1 y 2, se emplean propiedades de tipo String e Integer las cuales implementan la interface Comparable, por lo que solo se regresa el resultado de llamar la funcion compareTo de la propiedad respectiva. En el ejemplo 3 se utiliza una propiedad de tipo nativo y se muestra un ejemplo de como puede implementarse la funcion, utilizando las clases que envuelven a los tipos nativos (wrappers), evitando el uso de autoboxing y autounboxing.

En estos ejemplos, solo se emplea una propiedad, para implementar la funcionalidad. La recomendacion, es utilizar solo los atributos que forman la llave primaria (el concepto de base de datos). En caso de requerir utilizar mas de una propiedad, se incremanta el grado de complejidad. Como se muestra en el siguiente ejemplo.

public class ExamplePerson4 implements Comparable<ExamplePerson4> {

 private Integer idPart1;
 private Integer idPart2;
 private String name;
 private String surname;

 ...

 @Override
 public int compareTo(ExamplePerson4 o) {
  int result = this.idPart1.compareTo(o.idPart1);
  if(result == 0) {
   result = this.idPart2.compareTo(o.idPart2);
  }
  return result;
 }

}

Como se observa, si la comparacion de la primer propiedad es cero, hay que comparar la segunda propiedad y asi sucesivamente, hasta encontrar una distinta o ya no tener mas propiedades.

--- Actualizacion ---

En ocasiones, es necesario evitar que la comparacion genere una excepcion del tipo NullPointerException, cuando el parametro que recibe la funcion compareTo, es null. Para procesar el null, es necesario insertar un if para validar si es null, en caso de ser null, se regresa el valor necesario (normalmente 0), en caso contrario, se regresa el valor calculado, utilizando el algoritmo descrito anteriormente.

public class ExamplePerson5 implements Comparable<ExamplePerson5> {

 private Integer id;
 private String name;
 private String surname;

 ...

 @Override
 public int compareTo(ExamplePerson5 o) {
  return o == null ? 0 : this.id.compareTo(o.id);
 }

}

Existe la posibilidad de implmentarlo utilizando un try-catch, en vez de utilizar un if. Si bien en apariencia no se ejecutan 2 operaciones, cuando se emplea el if (primero la comparacion contra null y posteriormente la evaluacion del if en si). En la practica no es optimo, dado que cuando se recibe un null, se genera una excepcion, que implicitamente es, la creacion del objeto excepcion, el llenado del stack (que en el caso de un programa muy sencillo son 3 o 4 elementos en el stack, pero en el caso de sistemas complejos, pueden ser mas de 50 elementos).

public class ExamplePerson6 implements Comparable<ExamplePerson6> {

 private Integer id;
 private String name;
 private String surname;

 ...

 @Override
 public int compareTo(ExamplePerson6 o) {
  try {
   return this.id.compareTo(o.id);
  } catch (NullPointerException e) {
   return 0;
  }
 }

}

En conclusion, siempre es recomendable utilizar un if, si se necesita regresar un valor en caso de que el parametro sea null y evitar el uso de un try-catch.

miércoles, 26 de mayo de 2010

generics en C#, implementando GetHashCode, Equals y Comparable

A continuacion, la manera de utilizar generics en C#, para implementar las funciones GetHashCode y Equals, asi como la implementacion de IComparable. Este ejemplo es equivalente al ejemplo de java


01: using System;
02: using System.Collections.Generic;
03: 
04: namespace Test
05: {
06:     public abstract class GenericClass<T>
07:     {
08:         internal T id;
09: 
10:         public T Id
11:         {
12:             get
13:             {
14:                 return id;
15:             }
16:             set
17:             {
18:                 id = value;
19:             }
20:         }
21:         public override int GetHashCode()
22:         {
23:             return id.GetHashCode();
24:         }
25:         public override bool Equals(object obj)
26:         {
27:             return this == obj
28:                 || (((object)(id as GenericClass<T>) == null)
29:                     && Equals0((GenericClass<T>)obj));
30:         }
31:         public bool Equals(GenericClass<T> obj)
32:         {
33:             return this == obj || Equals0(obj);
34:         }
35:         private bool Equals0(GenericClass<T> obj)
36:         {
37:             return id.Equals(obj.id);
38:         }
39:     }
40: 
41:     public abstract class GenericClassComparable<T> : GenericClass<T>,
42:         IComparable<GenericClassComparable<T>> where T : IComparable<T>
43:     {
44:         public int CompareTo(GenericClassComparable<T> o)
45:         {
46:             return id.CompareTo(o.id);
47:         }
48:     }
49: }
50: 

Explicacion:
06-06: Declaracion de utilizacion del uso de generics
08-08: Declaracion del id.
10-20: Declaracion de los accesors para el id.
21-24: Definicion de la funcion GetHashCode, empleando las funciones propias del atributo id.
25-38: Definicion de multiples funciones Equals.
41-42: Declaracion del uso de IComparable
44-47: Definicion de la funcion CompareTo

Optimizacion:

sábado, 8 de mayo de 2010

implementando la funcion compareTo de Comparable con Generics en java

En esta ocasion, utilizando el codigo de la entrada anterior utilizando herencia en esta clase, se implementa Comparable, para poder utilizar la funcionalidad de Collections.




01: package test;
02: 
03: public abstract class GenericsBeanComparable<T extends Comparable<T>> extends
04:                 GenericsBean<T> implements Comparable<GenericsBeanComparable<T>> {
05: 
06:         public int compareTo(GenericsBeanComparable o) {
07:                 return this.id.compareTo(o.id);
08:         }
09: 
10: }

Explicacion:
03-04: Se define el tipo que se va a emplear , notese que T es Comparable, dando la posibilidad de utilizar clases como Long, Integer, String, etc.
06-08: Se define como se comparara la unica propiedad que conocemos (id) con el id del otro objeto.

Optimizacion:
  • Como en la clase padre, al implementar esta clase, implicitamente, se puede utilizar la funcionalidad de clases como Collections.sort o Collections.binarySearch. Ademas de implementar la funcionalidad de hashCode y equals, heredadas de la clase padre.

Nota:
  • La funcionalidad por defecto, solo compara la propiedad id, por lo que seria recomendable sobreescribir el metodo, para poder comparar otras propiedades, en caso de ser necesario.
Ejemplo:



01: package test;
02: 
03: public class Person extends GenericsBeanComparable<Integer> {
04: 
05:         private String name;
06:         private Integer age;
07: 
08:         public String getName() {
09:                 return name;
10:         }
11: 
12:         public void setName(String name) {
13:                 this.name = name;
14:         }
15: 
16:         public Integer getAge() {
17:                 return age;
18:         }
19: 
20:         public void setAge(Integer age) {
21:                 this.age = age;
22:         }
23: 
24: }

En este ejemplo se define la clase persona, la cual, tiene definido un id de tipo Integer, junto con las funciones hashCode, equals y CompareTo. definidas anteriormente, pueden crear 2 objetos distintos y determinar si son o no iguales, incluso ingresarlos en una tabla de hash (Hashtable o HashMap). E incluso, si se define una Lista de objetos Person y utilizar las funciones sort y binarySearch de Collections.