Tablas hash Juan Ramón Pérez Pérez Prácticas EDI - © Juan Ramón Pérez
¿Cómo funciona la implementación Java para las tablas hash? Paquete java.util Jerarquía de clases HashMap Importancia de los métodos hashCode() y equals() Prácticas EDI - © Juan Ramón Pérez
Jerarquía de clases de la API de Java (fragmento) Collection <<interface>> Map <<interface>> List <<interface>> Set <<interface>> AbstractMap <<abstracta>> ArrayList LinkedList AbstractSet <<abstracta>> HashMap HashTable HashSet Paquete java.util Prácticas EDI - © Juan Ramón Pérez
java.util.HashMap java.util.HashMap HashMap(int initialCapacity, float loadFactor) put(Object key, Object value): Object get(Object key): Object remove(Object key): Object containsKey(Object key): boolean containsValue(Object value): boolean size(): int [...] Insertar Buscar Borrar Prácticas EDI - © Juan Ramón Pérez
Uso de HashMap HashMap hm= new HashMap(); Mercancia m1= new Mercancia(); hm.put(m1.getCodigo(),m1); Mercancia m= hm.get(m1.getCodigo()); Prácticas EDI - © Juan Ramón Pérez
… Y si utilizamos una clave no String Imaginemos que queremos asociar cada mercancía con un objeto repartidor. Y para buscar los objetos mercancía utilizamos el repartidor. HashMap hm= new HashMap(); Repartidor rep1= new Repartidor(“Pepe”); Mercancia m1= new Mercancia(“Paquete fragil”); hm.put(rep1,m1); Repartidor rep= new Repartidor(“Pepe”); Mercancia m= hm.get(); Prácticas EDI - © Juan Ramón Pérez
Para que funcione el ejemplo anterior java.lang.Object Para insertar HashMap necesita un código hash del objeto que actúa como clave (Repartidor). No podemos utilizar directamente el de Object. Para buscar HashMap necesita el código hash y además poder comparar objetos Repartidor. hashCode(): int equals(Object): boolean Repartidor hashCode(): int equals(Object): boolean Prácticas EDI - © Juan Ramón Pérez
La búsqueda de objetos cuando hay colisiones hashCode()%B54 Fran HashMap hm= new HashMap(); Repartidor rep1= new Repartidor(“Pepe”); Mercancia m1= new Mercancia(“Paquete fragil”); Repartidor rep2= new Repartidor(“Fran”); Mercancia m5= new Mercancia(“Sobre documentos”); hm.put(rep1,m1); hm.put(rep2,m5); Repartidor rep= new Repartidor(“Fran”); Mercancia m= hm.get(rep); hashCode()%B54 Paquete frágil Pepe 54 hashCode()%B54 Sobre docum. Fran 97 Prácticas EDI - © Juan Ramón Pérez
Implementación de nuestra tabla hash Crear una tabla hash abierta genérica. Tamaño de la tabla debe de ser un número primo. Función de dispersión basada en las poténcias de 32 y optimizada con la regla de Horner incluida en el método hashCode() de los elementos que insertamos. Gestión de colisiones mediante listas de elementos. Que permita borrar los elementos. Prácticas EDI - © Juan Ramón Pérez
Tabla hash final TablaHash tabla[]: Lista; B: entero Utiliza el hashcode() de la clave del elemento que insertamos y le aplica el módulo de B En cada posición de la tabla hay una lista con todos los elementos que colisionaron TablaHash tabla[]: Lista; B: entero -calcularDispersion(Object clave): int Contenedor Pasamos ya como parámetros separados la clave y el elemento elemento: Object clave: String create(entero tam) insertar(String clave, Object obj); buscar(String clave): Object; borrar(String clave): boolean; toString(): String [...] create() Clase contenedor, además del elemento guardamos la clave Prácticas EDI - © Juan Ramón Pérez
Tareas Mejorar los métodos insertar y buscar para gestionar colisiones: Función de dispersión basada en hashCode() análoga a Java. Tabla hash abierta Añadir el método de borrar elementos Prácticas EDI - © Juan Ramón Pérez