Antes de iniciar a explicar el codigo, tengo que señalar que tanto la clase HashSet como la clase HashMap tienen una ventaja la cual es, que los valores que se van insertando en la coleccion internamente no tendran un orden especifico, esto se debe a que estas clases realizan un ordenamiento interno mediante el hashcode de el elemento(Objeto), por lo cual no sabremos que elemento traerá.
Esto nos da una ventaja para nosotros que es poder sobrescribir el metodo .hashCode() y .equals() para asi, si tenemos un objeto que tienen sus mismas caracteristicas y mismo hashcode no se agregue a la colección , una de las principales ventajas de este metodo es la rapidez en la insercion de los elemento si tenemos cientos de elementosque agregar, esta coleccion es la indicada para este trabajo.
El algoritmo de busqueda de un elemento en la colecion es el siguiente
- Encuentra el elemento (Objeto) mediante el hashcode. Imagínense varios personas en un salon con la misma edad.
- Ya que encontro el elemento mediante el hashcode se realiza la comparacion si el objeto es igual mediante el método .equals(). Imaginen que en ese mismo salon se esta buscando a una persona con un nombre y apellido especifico.
Lo primero será definir un objeto de tipo Alumnos.
public class Alumnos {
private int age;
private String name;
Alumnos(String name, int age){
this.name = name;
this.age = age;
}
}
Las variables age y name serán las necesarias para que se comparen los objetos y su hashcode.
Lo siguiente que haremos será insertar los objetos Alumnos en un HashSet.
Alumnos person1 = new Alumnos("Juan",18);
Alumnos person2 = new Alumnos("Miguel",25);
Alumnos person3 = new Alumnos("Luis",18);
Alumnos person4 = new Alumnos("Luis",18);
HashSet personas = new HashSet();
personas.add(person1);
personas.add(person2);
personas.add(person3);
personas.add(person4);
Si verificamos el tamaño del HashSet alumnos veremos que nos devuelve «4», ya que por defecto el HashSet no realiza ninguna comparación.
System.out.println(personas.size());
Ahora agregamos 4 objetos alumno a un HashMap.
Map m = new HashMap();
m.put(person1, "valor1");
m.put(person2, "valor2");
m.put(person3, "valor1");
m.put(person4, "mi valor");
El método .size() nos devolvera un tamaño de «4» ya que el HashMap tampoco realiza ninguna comparación. De igual manerá el método .keySet() devuelve todos los elementos del HashMap.
System.out.println(m.keySet());
System.out.println(m.size());
Ahora vamos a cambiar el comportamiento de la clase Alumnos para que al insertarlo en un HashMap o en un HashSet se valide si el elemento insertado ya existe.
Sobrescribimos el método .equals() de tal manera que dos objetos Alumno serán iguales si coinciden sus nombres.
@Override
public boolean equals(Object o) {
if (o instanceof Alumnos) {
Alumnos p = (Alumnos)o;
return this.name.equals(p.name);
} else {
return false;
}
}
De igual manera sobrescribimos el método .hashCode(). Para generar el hascode utilizamos la variable edad y la longitud del String, consiguiendo así un entero.
@Override
public int hashCode() {
return age * this.name.length();
}
Ahora, una vez sobrescritos los métodos .hashCode() y .equals(), si verificamos el tamaño del HashSet alumnos veremos que nos devuelve «3» ya que, si hay un elemento igual, el metodo .add() devolvera false.
Map m = new HashMap();
De igual manera el método .size() sobre el HashMap.keySet() los nombres de 3 alumnos ya que el método .put() habrá devuelto false al insertar objetos iguales.
System.out.println(m.keySet());
System.out.println(m.size());
Una cosa que hay que tener en cuenta es que si se sobreescribe solo uno de sus metodos ya sea .hashCode() o .equals() no tendremos el comportamiento deseado. Hay que sobrescribir los dos.