metodos java hashmap hashcode hash-function

metodos - ¿Cómo maneja Java HashMap diferentes objetos con el mismo código hash?



map string string java (16)

dos objetos son iguales, implica que tienen el mismo código hash, pero no viceversa

Actualización de Java 8 en HashMap-

haces esta operación en tu código -

myHashmap.put("old","key-value-pair"); myHashMap.put("very-old","old-key-value-pair");

entonces, suponga que su código hash devuelto para ambas claves "old" y "very-old" es el mismo. Entonces, ¿qué pasará?

myHashMap es un HashMap, y supongamos que inicialmente no especificó su capacidad. Así que la capacidad por defecto según java es 16. Entonces, tan pronto como iniciaste hashmap usando la nueva palabra clave, creó 16 cubos. ahora cuando ejecutaste la primera declaración-

myHashmap.put("old","key-value-pair");

luego se calcula el hashcode para "old" , y debido a que el código hash también puede ser un número entero muy grande, java lo hizo internamente - (hash es hashcode aquí y >>> está a la derecha)

hash XOR hash >>> 16

entonces, para obtener una imagen más grande, se devolverá algún índice, que estaría entre 0 y 15. Ahora su par de valores clave "old" y "key-value-pair" se convertiría en la clave del objeto de entrada y la variable de instancia de valor. y luego este objeto de entrada se almacenará en el depósito, o puede decir que en un índice particular, este objeto de entrada se almacenará.

FYI- Entry es una clase en Map interface- Map.Entry, con esta firma / definición

class Entry{ final Key k; value v; final int hash; Entry next; }

ahora cuando ejecutas la siguiente declaración -

myHashmap.put("very-old","old-key-value-pair");

y "very-old" da el mismo código hash como "old" , por lo que este nuevo par de valores clave se envía nuevamente al mismo índice o al mismo cubo. Pero como este depósito no está vacío, la next variable del objeto Entry se usa para almacenar este nuevo par de valores clave.

y esto se almacenará como lista enlazada para cada objeto que tenga el mismo código hash, pero se especifica un TRIEFY_THRESHOLD con el valor 6. por lo tanto, después de esto, la lista vinculada se convierte al árbol balanceado (árbol rojo-negro) con el primer elemento como raíz.

Según mi entendimiento, pienso:

  1. Es perfectamente legal que dos objetos tengan el mismo código hash.
  2. Si dos objetos son iguales (usando el método equals ()), entonces tienen el mismo código hash.
  3. Si dos objetos no son iguales, entonces no pueden tener el mismo código hash

¿Estoy en lo correcto?

Ahora bien, si estoy en lo correcto, tengo la siguiente pregunta: HashMap usa internamente el código hash del objeto. Entonces, si dos objetos pueden tener el mismo código hash, ¿cómo puede el HashMap rastrear qué tecla usa?

¿Alguien puede explicar cómo el HashMap usa internamente el código hash del objeto?


Aquí hay una descripción aproximada del mecanismo de HashMap , para Java 8 versión Java 8 (podría ser ligeramente diferente de Java 6) .

Clases internas

  • Map.Entry
    Representar una sola entidad en el mapa, la entidad clave / valor,
  • HashMap.Node
    Versión de lista enlazada de nodo,

    Podría representar:

    • un cubo de hash,
      porque tiene una propiedad hash,
    • un nodo en la lista individualmente vinculada, (por lo tanto, también encabezado de la lista enlazada)
  • HashMap.TreeNode
    Versión de árbol del nodo.

Estructuras de datos

  • Tabla de picadillo
    El valor de hash se calcula a través de hash() en la tecla, y decide qué cubo de la tabla hash usar para una clave determinada.
  • Lista enlazada (individualmente)
    Cuando el recuento de elementos en un cubo es pequeño, se usa una lista vinculada individualmente.
  • árbol rojo-negro
    Cuando el recuento de elementos en un cubo es grande, se usa un árbol rojo-negro.

Campos en HashMap

  • Node[] table
    La tabla del cubo, (encabezado de las listas enlazadas).
    Si un cubo no contiene elementos, entonces es nulo, por lo tanto, solo ocupa espacio de una referencia,
  • Set<Map.Entry> entrySet conjunto de entidades,
  • int size
    número de entidades,
  • float loadFactor
    indica qué tan completa está permitida la tabla hash,
  • int threshold
    el siguiente tamaño al cual redimensionar, threshold = capacity * loadFactor

Interno - métodos

  • int hash(key)
    figura hash,
  • hash de mapa a cubo
    Usa la siguiente lógica

static int hashToBucket(int tableSize, int hash) { return (tableSize - 1) & hash; }

capacidad

capacidad, significa recuento de cubo de table.length , podría table.length de table.length , también podría calcularse mediante threshold y loadFactor , por lo tanto, no es necesario definirlo como un campo de clase.

capacity() : obtener capacidad efectiva.

actuación

  • get & put
    tiene complejidad de tiempo O (1), porque:
    • Se accede al cubo a través del índice.
    • la lista enlazada en cada cubo es de poca longitud,
    • el tamaño del árbol también es limitado, porque ampliará la capacidad y volverá a hash cuando aumente el recuento de elementos, por lo que podría verse como O (1), no como O (log N),

Operación

  • Encontrar entidad por clave
    Primero encuentre la cubeta por valor de hash, luego bucle de lista enlazada o busque árbol ordenado.
  • Agregar entidad con clave Primero encuentre el depósito según el valor hash de la clave.
    Luego intente encontrar el valor:
    • Si lo encuentra, reemplace el valor.
    • De lo contrario, agregue un nuevo nodo al principio de la lista enlazada, o inserte en el árbol ordenado.
  • Cambiar el tamaño
    Cuando se alcance el threshold , se duplicará la capacidad de table.lenght ( table.lenght ), luego se realizará un hash en todos los elementos para reconstruir la tabla. Esta podría ser una operación costosa.

Cada objeto de entrada representa un par clave-valor. El siguiente campo se refiere a otro objeto de entrada si un segmento tiene más de 1 entrada.

A veces puede ocurrir que hashCodes para 2 objetos diferentes sea el mismo. En este caso, se guardarán 2 objetos en un cubo y se presentarán como LinkedList. El punto de entrada es un objeto agregado más recientemente. Este objeto se refiere a otro objeto con el siguiente campo y uno. La última entrada se refiere a null. Cuando crea HashMap con el constructor predeterminado

Array se crea con el tamaño 16 y el equilibrio de carga predeterminado de 0,75.

(Source)


Como se dice, una imagen vale más que 1000 palabras. Yo digo: algún código es mejor que 1000 palabras. Aquí está el código fuente de HashMap. Obtener método:

/** * Implements Map.get and related methods * * @param hash hash for key * @param key the key * @return the node, or null if none */ final Node<K,V> getNode(int hash, Object key) { Node<K,V>[] tab; Node<K,V> first, e; int n; K k; if ((tab = table) != null && (n = tab.length) > 0 && (first = tab[(n - 1) & hash]) != null) { if (first.hash == hash && // always check first node ((k = first.key) == key || (key != null && key.equals(k)))) return first; if ((e = first.next) != null) { if (first instanceof TreeNode) return ((TreeNode<K,V>)first).getTreeNode(hash, key); do { if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) return e; } while ((e = e.next) != null); } } return null; }

Entonces queda claro que el hash se usa para encontrar el "cubo" y el primer elemento siempre se revisa en ese cubo. De lo contrario, se utiliza el mismo valor de la clave para encontrar el elemento real en la lista vinculada.

Veamos el método put() :

/** * Implements Map.put and related methods * * @param hash hash for key * @param key the key * @param value the value to put * @param onlyIfAbsent if true, don''t change existing value * @param evict if false, the table is in creation mode. * @return previous value, or null if none */ final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) { Node<K,V>[] tab; Node<K,V> p; int n, i; if ((tab = table) == null || (n = tab.length) == 0) n = (tab = resize()).length; if ((p = tab[i = (n - 1) & hash]) == null) tab[i] = newNode(hash, key, value, null); else { Node<K,V> e; K k; if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) e = p; else if (p instanceof TreeNode) e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value); else { for (int binCount = 0; ; ++binCount) { if ((e = p.next) == null) { p.next = newNode(hash, key, value, null); if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st treeifyBin(tab, hash); break; } if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) break; p = e; } } if (e != null) { // existing mapping for key V oldValue = e.value; if (!onlyIfAbsent || oldValue == null) e.value = value; afterNodeAccess(e); return oldValue; } } ++modCount; if (++size > threshold) resize(); afterNodeInsertion(evict); return null; }

Es un poco más complicado, pero queda claro que el nuevo elemento se coloca en la pestaña en la posición calculada en función del hash:

i = (n - 1) & hash aquí i es el índice donde se colocará el nuevo elemento (o es el "cubo"). n es el tamaño de la matriz de tab (matriz de "cubos").

Primero, se intenta ubicarlo como el primer elemento de ese "cubo". Si ya hay un elemento, añada un nuevo nodo a la lista.


El hashcode determina qué segmento del hashmap verificará. Si hay más de un objeto en el depósito, se realiza una búsqueda lineal para encontrar qué elemento en el depósito es igual al elemento deseado (utilizando el método equals() ).

En otras palabras, si tiene un código hash perfecto, el acceso hashmap es constante, nunca tendrá que iterar a través de un depósito (técnicamente también debería tener cubos MAX_INT, la implementación Java puede compartir algunos códigos hash en el mismo depósito para reducir los requisitos de espacio). Si tienes el peor código hash (siempre devuelve el mismo número), tu acceso a hashmap se vuelve lineal, ya que tienes que buscar en cada elemento del mapa (todos están en el mismo cubo) para obtener lo que deseas.

La mayoría de las veces un código hash bien escrito no es perfecto, pero es lo suficientemente único como para darle un acceso más o menos constante.


El mapa Hash funciona según el principio de hashing

El método HashMap get (Key k) llama al método hashCode en el objeto clave y aplica hashValue devuelto a su propia función hash estática para encontrar una ubicación de depósito (matriz de respaldo) donde las claves y valores se almacenan en forma de una clase anidada llamada Entrada (Mapa. Entrada) . Por lo tanto, ha concluido que, desde la línea anterior, tanto la clave como el valor se almacenan en el depósito como una forma de objeto de Entrada. Entonces, pensar que solo se almacena el valor en el cubo no es correcto y no dará una buena impresión en el entrevistador.

  • Siempre que llamemos al método get (Key k) en el objeto HashMap. Primero comprueba si la clave es nula o no. Tenga en cuenta que solo puede haber una clave nula en HashMap.

Si la clave es nula, las claves nulas siempre se asignan al hash 0, por lo tanto, al índice 0.

Si la clave no es nula, llamará a la función de hash en el objeto clave, vea la línea 4 en el método anterior, es decir, key.hashCode (), luego de que key.hashCode () devuelva hashValue, la línea 4 se vea como

int hash = hash(hashValue)

y ahora, aplica hashValue devuelto en su propia función hash.

Podríamos preguntarnos por qué estamos calculando nuevamente el hashvalue usando hash (hashValue). La respuesta es Defiende contra funciones hash de baja calidad.

Ahora el valor de hash final se usa para encontrar la ubicación del depósito en el que está almacenado el objeto Entry. El objeto de entrada se almacena en el cubo de esta manera (hash, clave, valor, índice de cubo)


Estás equivocado en el punto tres. Dos entradas pueden tener el mismo código hash pero no ser iguales. Eche un vistazo a la implementación de HashMap.get desde OpenJdk . Puede ver que comprueba que los hashes son iguales y las claves son iguales. Si el punto tres fuera cierto, entonces no sería necesario verificar que las claves sean iguales. El código hash se compara antes que la clave porque el primero es una comparación más eficiente.

Si está interesado en aprender un poco más sobre esto, eche un vistazo al artículo de Wikipedia sobre resolución de colisión de Open Addressing , que creo que es el mecanismo que utiliza la implementación de OpenJdk. Ese mecanismo es sutilmente diferente al enfoque "cubo" que menciona una de las otras respuestas.


Esta es una de las preguntas más confusas para muchos de nosotros en las entrevistas. Pero no es tan complejo.


Sabemos

  • HashMap almacena el par clave-valor en Map.Entry (todos lo sabemos)

  • HashMap funciona con el algoritmo hash y utiliza los métodos hashCode () y equals () en los métodos put () y get (). (incluso nosotros sabemos esto)

  • When we call put method by passing key-value pair, HashMap uses Key **hashCode()** with hashing to **find out the index** to store the key-value pair. (this is important)

  • The Entry is **stored in the LinkedList**, so if there are already existing entry, it uses **equals() method to check if the passed key already exists** (even this is important)

  • en caso afirmativo, sobrescribe el valor; de lo contrario, crea una nueva entrada y almacena esta entrada clave-valor.

  • Cuando llamamos al método get pasando Key, de nuevo usa el hashCode () para encontrar el índice en la matriz y luego utiliza el método equals () para encontrar la entrada correcta y devolver su valor. (ahora esto es obvio)

ESTA IMAGEN TE AYUDARÁ A ENTENDER:

Edición de septiembre de 2017: aquí vemos cómo se usa el valor de hash junto con iguales después de encontrar el cubo.

if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { }


No entraré en detalles sobre cómo funciona HashMap, pero daré un ejemplo para que podamos recordar cómo funciona HashMap al relacionarlo con la realidad.

Tenemos Key, Value, HashCode y bucket.

Por algún tiempo, relacionaremos cada uno de ellos con lo siguiente:

  • Cubo -> Una sociedad
  • HashCode -> Dirección de la sociedad (única siempre)
  • Valor -> Una casa en la sociedad
  • Clave -> Domicilio de la casa.

Usando Map.get (clave):

Stevie quiere llegar a la casa de su amigo (Josse) que vive en una villa en una sociedad VIP, que sea la sociedad JavaLovers. La dirección de Josse es su SSN (que es diferente para todos). Se mantiene un índice en el que encontramos el nombre de la Sociedad basado en el SSN. Este índice se puede considerar como un algoritmo para averiguar el HashCode.

  • Nombre de la Sociedad SSN
  • 92313 (Josse''s) - JavaLovers
  • 13214 - AngularJSLovers
  • 98080 - JavaLovers
  • 53808 - BiologyLovers
  1. Este SSN (clave) primero nos da un HashCode (de la tabla de índice) que no es más que el nombre de Society.
  2. Ahora, las casas múltiples pueden estar en la misma sociedad, entonces el HashCode puede ser común.
  3. Supongamos que la Sociedad es común para dos casas, ¿cómo vamos a identificar a qué casa vamos, sí, utilizando la clave (SSN) que no es más que la dirección de la casa?

Usando Map.put (clave, Valor)

Esto encuentra una sociedad adecuada para este Valor al encontrar el Código Hash y luego se almacena el valor.

Espero que esto ayude y esto está abierto para modificaciones.


Puede encontrar información excelente en http://javarevisited.blogspot.com/2011/02/how-hashmap-works-in-java.html

Para resumir:

HashMap funciona según el principio de hashing

put (clave, valor): HashMap almacena la clave y el objeto de valor como Map.Entry. Hashmap aplica hashcode (clave) para obtener el cubo. si hay una colisión, HashMap usa LinkedList para almacenar objetos.

get (clave): HashMap usa el código hash del objeto clave para encontrar la ubicación del segmento y luego llama al método keys.equals () para identificar el nodo correcto en LinkedList y devolver el objeto de valor asociado para esa clave en Java HashMap.


Tu tercera afirmación es incorrecta.

Es perfectamente legal que dos objetos desiguales tengan el mismo código hash. HashMap utiliza como un "filtro de primer paso" para que el mapa pueda encontrar rápidamente las posibles entradas con la clave especificada. Las claves con el mismo código hash se prueban para determinar la igualdad con la clave especificada.

No desearía un requisito de que dos objetos desiguales no pudieran tener el mismo código hash, ya que de lo contrario eso limitaría a 2 32 posibles objetos. (También significaría que diferentes tipos ni siquiera podrían usar los campos de un objeto para generar códigos hash, ya que otras clases podrían generar el mismo hash).


Un hashmap funciona así (esto es un poco simplificado, pero ilustra el mecanismo básico):

Tiene una serie de "cubos" que utiliza para almacenar los pares clave-valor. Cada segmento tiene un número único, eso es lo que identifica el cubo. Cuando coloca un par de clave-valor en el mapa, el hashmap buscará el código hash de la clave y almacenará el par en el depósito cuyo identificador es el código hash de la clave. Por ejemplo: el código hash de la clave es 235 -> el par se almacena en el número de cesta 235. (Tenga en cuenta que un depósito puede almacenar más de un par clave-valor).

Cuando busca un valor en el hashmap, al darle una clave, primero verá el código hash de la clave que le dio. El hashmap buscará en el cubo correspondiente y luego comparará la clave que proporcionó con las claves de todos los pares del cubo, comparándolas con equals() .

Ahora puede ver cómo esto es muy eficiente para buscar pares clave-valor en un mapa: mediante el código hash de la clave, el hashmap sabe inmediatamente en qué cubo buscar, de modo que solo tiene que probar contra qué está en ese cubo.

Al observar el mecanismo anterior, también puede ver qué requisitos son necesarios en los métodos de claves hashCode() y equals() :

  • Si dos claves son iguales ( equals() devuelve true cuando las compara), su método hashCode() debe devolver el mismo número. Si las claves lo infringen, entonces las claves que son iguales podrían almacenarse en diferentes segmentos, y el hashmap no podría encontrar pares clave-valor (porque se verá en el mismo cubo).

  • Si dos claves son diferentes, entonces no importa si sus códigos hash son iguales o no. Se almacenarán en el mismo cubo si sus códigos hash son iguales, y en este caso, el hashmap usará equals() para diferenciarlos.


Va a ser una respuesta larga, toma un trago y sigue leyendo ...

Hashing se trata de almacenar un par clave-valor en la memoria que se puede leer y escribir más rápido. Almacena claves en una matriz y valores en LinkedList.

Digamos que quiero almacenar 4 pares de valores clave:

{ “girl” => “ahhan” , “misused” => “Manmohan Singh” , “horsemints” => “guess what”, “no” => “way” }

Entonces, para almacenar las claves necesitamos una matriz de 4 elementos. Ahora, ¿cómo puedo asignar una de estas 4 claves a 4 índices de matriz (0,1,2,3)?

Entonces java encuentra el hashCode de claves individuales y las asigna a un índice de matriz particular. Hashcode Formulas es -

1) reverse the string. 2) keep on multiplying ascii of each character with increasing power of 31 . then add the components . 3) So hashCode() of girl would be –(ascii values of l,r,i,g are 108, 114, 105 and 103) . e.g. girl = 108 * 31^0 + 114 * 31^1 + 105 * 31^2 + 103 * 31^3 = 3173020

Hash y chica !! Sé lo que estás pensando. Tu fascinación por ese dúo salvaje podría hacerte perder algo importante.

¿Por qué java lo multiplica con 31?

Es porque, 31 es un primo impar en la forma 2 ^ 5 - 1. Y el primo impar reduce la probabilidad de colisión hash

Ahora, ¿cómo se correlaciona este código hash con un índice de matriz?

la respuesta es Hash Code % (Array length -1) . Entonces, “girl” está mapeada (3173020 % 3) = 1 en nuestro caso. que es el segundo elemento de la matriz.

y el valor "ahhan" se almacena en una LinkedList asociada con el índice 1 de matriz.

HashCollision - Si intentas encontrar hasHCode de las teclas “misused” y “horsemints” usando las fórmulas descritas anteriormente, verás que ambas nos dan el mismo 1069518484 . Whooaa !! lección aprendida -

2 objetos iguales deben tener el mismo código hash, pero no hay garantía si el hashCode coincide, entonces los objetos son iguales. Por lo tanto, debe almacenar los valores correspondientes a "uso indebido" y "horsemints" en el depósito 1 (1069518484% 3).

Ahora el mapa hash se ve como ...

Array Index 0 – Array Index 1 - LinkedIst (“ahhan” , “Manmohan Singh” , “guess what”) Array Index 2 – LinkedList (“way”) Array Index 3 –

Ahora, si algún cuerpo intenta encontrar el valor de la clave “horsemints” , java rápidamente encontrará el hashCode, lo module y comienza a buscar su valor en el LinkedList correspondiente index 1 . De esta forma, no es necesario buscar los 4 índices de matriz, lo que hace que el acceso a los datos sea más rápido.

Pero, espera, un segundo. hay 3 valores en ese linkedList index 1 de Array correspondiente, ¿cómo se averigua cuál fue el valor para la clave "horsemints"?

En realidad, mentí cuando dije que HashMap solo almacena valores en LinkedList.

Almacena ambos pares de valores clave como entrada de mapa. Entonces, en realidad Map se ve así.

Array Index 0 – Array Index 1 - LinkedIst (<”girl” => “ahhan”> , <” misused” => “Manmohan Singh”> , <”horsemints” => “guess what”>) Array Index 2 – LinkedList (<”no” => “way”>) Array Index 3 –

Ahora puede ver Mientras atraviesa LinkedList correspondiente a ArrayIndex1, en realidad compara la clave de cada entrada de LinkedList con "horsemints" y cuando encuentra una, simplemente devuelve el valor de la misma.

Espero que te hayas divertido mientras lo lees :)


En una forma veraniega de ¿Cómo funciona hashMap en Java?

HashMap funciona según el principio de hashing, hemos puesto put () y get () para almacenar y recuperar objetos de HashMap. Cuando pasamos el método de clave y valor a put () para almacenar en HashMap, utiliza el método key hashcode () para calcular hashcode y aplicando hash en ese código hash, identifica la ubicación del depósito para almacenar el objeto de valor. Mientras recupera, utiliza el método del objeto clave igual para descubrir el par de valor de clave correcto y el objeto de valor de retorno asociado con esa clave. HashMap utiliza la lista vinculada en caso de colisión y el objeto se almacenará en el siguiente nodo de la lista vinculada. Además, HashMap almacena ambas claves + valor de tupla en cada nodo de la lista vinculada.


HashMap es una matriz de objetos de Entry .

Considere HashMap como solo una matriz de objetos.

Eche un vistazo a lo que es este Object :

static class Entry<K,V> implements Map.Entry<K,V> { final K key; V value; Entry<K,V> next; final int hash; … }

Cada objeto de Entry representa un par clave-valor. El campo next refiere a otro objeto de Entry si un contenedor tiene más de una Entry .

A veces puede suceder que los códigos hash para 2 objetos diferentes sean los mismos. En este caso, se guardarán dos objetos en un cubo y se presentarán como una lista vinculada. El punto de entrada es el objeto agregado más recientemente. Este objeto se refiere a otro objeto con el next campo y así sucesivamente. La última entrada se refiere a null .

Cuando crea un HashMap con el constructor predeterminado

HashMap hashMap = new HashMap();

La matriz se crea con el tamaño 16 y el saldo de carga predeterminado de 0,75.

Agregar un nuevo par clave-valor

  1. Calcular hashcode para la clave
  2. Calcular posición hash % (arrayLength-1) donde debe colocarse el elemento (número de depósito)
  3. Si intenta agregar un valor con una clave que ya se ha guardado en HashMap , el valor se sobrescribe.
  4. De lo contrario, el elemento se agrega al cubo.

Si el contenedor ya tiene al menos un elemento, se agrega uno nuevo y se coloca en la primera posición del contenedor. Su next campo se refiere al antiguo elemento.

Supresión

  1. Calcular hashcode para la clave dada
  2. Calcular el número del cubo hash % (arrayLength-1)
  3. Obtenga una referencia al primer objeto de entrada en el depósito y por medio del método igual itere sobre todas las entradas en el depósito dado. Eventualmente encontraremos la Entry correcta. Si no se encuentra el elemento deseado, devuelva null

import java.util.HashMap; public class Students { String name; int age; Students(String name, int age ){ this.name = name; this.age=age; } @Override public int hashCode() { System.out.println("__hash__"); final int prime = 31; int result = 1; result = prime * result + age; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { System.out.println("__eq__"); if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Students other = (Students) obj; if (age != other.age) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } public static void main(String[] args) { Students S1 = new Students("taj",22); Students S2 = new Students("taj",21); System.out.println(S1.hashCode()); System.out.println(S2.hashCode()); HashMap<Students,String > HM = new HashMap<Students,String > (); HM.put(S1, "tajinder"); HM.put(S2, "tajinder"); System.out.println(HM.size()); } } Output: __ hash __ 116232 __ hash __ 116201 __ hash __ __ hash __ 2

Entonces, aquí vemos que si los objetos S1 y S2 tienen contenido diferente, entonces estamos bastante seguros de que nuestro método Hashcode invalidado generará Hashcode (116232,11601) diferente para ambos objetos. AHORA, ya que hay diferentes códigos hash, por lo que ni siquiera se molestará en llamar al método EQUALS. Porque un Hashcode diferente GARANTIZA el contenido DIFERENTE en un objeto.

public static void main(String[] args) { Students S1 = new Students("taj",21); Students S2 = new Students("taj",21); System.out.println(S1.hashCode()); System.out.println(S2.hashCode()); HashMap<Students,String > HM = new HashMap<Students,String > (); HM.put(S1, "tajinder"); HM.put(S2, "tajinder"); System.out.println(HM.size()); } } Now lets change out main method a little bit. Output after this change is __ hash __ 116201 __ hash __ 116201 __ hash __ __ hash __ __ eq __ 1 We can clearly see that equal method is called. Here is print statement __eq__, since we have same hashcode, then content of objects MAY or MAY not be similar. So program internally calls Equal method to verify this. Conclusion If hashcode is different , equal method will not get called. if hashcode is same, equal method will get called. Thanks , hope it helps.