2012-06-25 29 views
14

Tengo entendido que dos objetos desiguales pueden tener el mismo código hash. ¿Cómo se manejaría esto al agregar o recuperar desde un Java de HashMap?¿Qué sucede si dos objetos diferentes tienen el mismo código hash?

+0

BTW: Puede crear muchos valores Long con el mismo código hash fácilmente para probar esto. 'new Long (n * 0x100000001L)' todos tienen un hashCode de 0 para 'n> = 0' –

Respuesta

22

Se agregarán al mismo cubo y se usará equals() para distinguirlos. Cada segmento puede contener una lista de objetos con el mismo código hash.

En teoría, puede devolver el mismo número entero que un código hash para cualquier objeto de una clase determinada, pero eso significa que perderá todos los beneficios de rendimiento del mapa hash y, de hecho, almacenará objetos en una lista.

+0

¿No se aplica un hash suplementario por defecto para un Hashmap para evitar que esto suceda y presente cierta distribución? – Ajay

+0

Punto adicional sobre el rendimiento, en java8, cuando tenemos demasiadas claves desiguales que proporcionan el mismo código hash (índice), el número de elementos en un depósito aumenta más allá de cierto umbral (TREEIFY_THRESHOLD = 8), el contenido de ese depósito cambia de uso una lista vinculada de objetos de entrada a un árbol equilibrado. Esto teóricamente mejora el rendimiento en el peor de los casos desde O (n) hasta O (log n). –

5

En HashMap, las claves junto con sus valores asociativos se almacenan en un nodo de lista vinculada en el depósito y las claves se comparan esencialmente en hashmap utilizando el método equals() y no mediante hashcode.

hm.put("a","aValue"); // Suppose hashcode created for key "a" is 209 
hm.put("b","bValue"); // Here hashcode created for key "b" is 209 as well. 
  • If a.equals(b) vuelve true, bValue reemplazará aValue y se devolverá bValue.
  • a.equals(b) Si vuelve false, otro nodo se creará en la lista del cubo, por lo que cuando se llama a get("b") obtendrá bValue desde a.equals(b) es false.
+0

¿Cómo puedo recuperar el valor de a si el hashcode es el mismo? Me dará bValue, pero quiero un valor. Es eso posible ? – Sanket

0

En ese caso, podría usar IdentityHashMap, donde diferentes objetos con el mismo hash se consideran diferentes en función de sus identidades.

0

Cuando dos objetos desiguales tienen el mismo valor hash, esto provoca una colisión en la tabla hash, porque ambos objetos quieren estar en la misma ranura (a veces llamado cubo). El algoritmo hash debe resolver tales colisiones. Volviendo a los recuerdos borrosos de mi curso de algoritmos universitarios, recuerdo tres formas básicas de hacerlo:

  1. Busque la siguiente ranura vacía en la tabla hash y coloque el objeto allí. Pros: fácil de implementar, contras: puede llevar a la agrupación de objetos y degradar el rendimiento, la capacidad puede exceder
  2. Tener una función hash secundaria para usar cuando hay un conflicto: Ventajas: generalmente rápido, contras: debe escribir una segunda función hash y aún puede obtener colisiones, y la capacidad puede excederse
  3. Haga una lista enlazada de objetos desde la ranura en conflicto de la tabla hash. Pros/Contras: generalmente rápido para los factores de función hash y de carga decente, pero pueden degradar a la búsqueda lineal en peor de los casos

Creo que las clases de hash de Java utilizan el tercer método, pero podrían usar un enfoque de combinación. Sin embargo, la clave del buen hashing es asegurarse de que la tabla hash tenga una capacidad lo suficientemente grande y de escribir buenas funciones hash. Una tabla hash que solo tiene tantos cubos como los objetos que contiene probablemente tenga conflictos. Por lo general, desea que la tabla hash sea aproximadamente dos veces más grande que la cantidad de objetos que almacena. El HashMap de Java crecerá según sea necesario, pero puede darle una capacidad de inicio y un factor de carga si lo desea.

La función hash depende del programador. Podrías devolver 0 para todos los objetos, pero eso significará que el hash (tanto de almacenamiento como de recuperación) se convertirá en O (n) en lugar de O (1) ... o en términos simples, será dog slow.

Referencia: http://www.coderanch.com/t/540275/java/java/objects-hashcode-HashMap-retrieve-objects

1

HashMap está trabajando en el concepto de hash y la indexación. Internamente, HashMap almacena valores en la matriz de nodos. Cada nodo se comporta como LinkedList.

Cada nodo de lista enlazada tienen 4 valores:

  1. int hash
  2. K key
  3. V value
  4. estructura
  5. Node<K, V> next

HashMap interna:

HashMap Internal structure Image

Al insertar el valor en HashMap, se genera el primer hashcode de la clave y, basado en algún algoritmo, calculará el índice.

Por lo tanto, nuestro valor se almacenará en un índice específico con código hash, clave, valor y dirección del siguiente elemento.

Al recuperar el valor de HashMap, primero se generará el código hash y luego se indexará (de la misma manera que en el momento de la inserción). Al obtener el valor del índice, primero se buscará el código hash, si hashcode coincidirá, solo se buscará la clave del nodo mediante el método equals. Si la clave coincidirá, solo devolverá el valor o comprobará el siguiente nodo con el mismo código hash.

Cuestiones relacionadas