¿Cuál es el código hash de un objeto si hashCode () no se reemplaza?

Si el método hashCode () no se reemplaza, ¿cuál será el resultado de invocar hashCode () en cualquier objeto en Java?

Normalmente, hashCode () simplemente devuelve la dirección del objeto en la memoria si no la anula.

De 1 :

Tanto como sea razonablemente práctico, el método hashCode definido por el objeto de clase devuelve enteros distintos para objetos distintos. (Esto se implementa típicamente al convertir la dirección interna del objeto en un entero, pero esta técnica de implementación no es requerida por el lenguaje de progtwigción JavaTM).

En HotSpot JVM de forma predeterminada en la primera invocación de Object.hashCode no sobrecargado o System.identityHashCode se genera un número aleatorio y se almacena en el encabezado del objeto. Las llamadas consiguientes a Object.hashCode o System.identityHashCode simplemente extraen este valor del encabezado. Por defecto, no tiene nada en común con el contenido del objeto o la ubicación del objeto, solo un número aleatorio. Este comportamiento se controla mediante la -XX:hashCode=n HotSpot JVM, que tiene los siguientes valores posibles:

  • 0: usar generador aleatorio global. Esta es la configuración predeterminada en Java 7. Tiene la desventaja de que las llamadas simultáneas desde múltiples hilos pueden causar una condición de carrera que dará como resultado la generación del mismo código hash para diferentes objetos. También en entornos altamente concurrentes, las demoras son posibles debido a la contención (usando la misma región de memoria de diferentes núcleos de CPU).
  • 5: utilice algún generador aleatorio xor-shift local de subprocesos que esté libre de las desventajas anteriores. Esta es la configuración predeterminada en Java 8.
  • 1: utilice un puntero de objeto mezclado con algún valor aleatorio que se modifique en los eventos “pare el mundo”, por lo que entre eventos stop-the-world (como recolección de basura) los hashCodes generados son estables (para fines de prueba / depuración)
  • 2: use siempre 1 (para fines de prueba / depuración)
  • 3: utilizar números de autoincrementing (para fines de prueba / depuración, también se utiliza el contador global, por lo tanto, son posibles las condiciones de contención y de carrera)
  • 4: utilice el puntero del objeto recortado a 32 bits si es necesario (para propósitos de prueba / depuración)

Tenga en cuenta que incluso si establece -XX:hashCode=4 , el hashCode no siempre apuntará a la dirección del objeto. Object se puede mover más tarde, pero hashCode se mantendrá igual. Además, las direcciones de los objetos están mal distribuidas (si su aplicación no usa tanta memoria, la mayoría de los objetos estarán ubicados cerca unos de otros), por lo que puede terminar teniendo tablas hash desbalanceadas si usa esta opción.

La implementación de hashCode() puede diferir de una clase a otra, pero el contrato para hashCode() es muy específico y se establece de forma clara y explícita en los Javadocs :

Devuelve un valor de código hash para el objeto. Este método es compatible con el beneficio de hashtables como los proporcionados por java.util.Hashtable.

El contrato general de hashCode es:

  • Cada vez que se invoca en el mismo objeto más de una vez durante la ejecución de una aplicación Java, el método hashCode debe devolver el mismo entero de forma consistente, siempre que no se modifique la información utilizada en comparaciones iguales en el objeto. Este entero no necesita ser consistente desde una ejecución de una aplicación hasta otra ejecución de la misma aplicación.
  • Si dos objetos son iguales de acuerdo con el método equals (Object), entonces llamar al método hashCode en cada uno de los dos objetos debe producir el mismo resultado entero.
  • No es necesario que si dos objetos son desiguales de acuerdo con el método equals (java.lang.Object), al invocar el método hashCode en cada uno de los dos objetos se produzcan resultados enteros distintos. Sin embargo, el progtwigdor debe tener en cuenta que la producción de resultados enteros distintos para objetos desiguales puede mejorar el rendimiento de hashtables.

Tanto como sea razonablemente práctico, el método hashCode definido por el objeto de clase devuelve enteros distintos para objetos distintos. (Esto se implementa típicamente al convertir la dirección interna del objeto en un entero, pero esta técnica de implementación no es requerida por el lenguaje de progtwigción JavaTM).

hashCode() está estrechamente relacionado con equals() y si anula equals() , también debe anular hashCode() .

Si hashcode no se reemplaza, se llamará a hashcode de Object, aquí hay un extracto de su javadoc:

Tanto como sea razonablemente práctico, el método hashCode definido por el objeto de clase devuelve enteros distintos para objetos distintos. (Esto se implementa típicamente al convertir la dirección interna del objeto en un entero, pero esta técnica de implementación no es requerida por el lenguaje de progtwigción JavaTM).

la implementación predeterminada de hashcode proporciona la dirección interna del objeto en el jvm, como un entero de 32 bits. Por lo tanto, dos objetos diferentes (en memoria) tendrán diferentes códigos hash.

Esto es consistente con la implementación predeterminada de iguales. Si desea anular iguales para sus objetos, tendrá que adaptar hashCode para que sean consistentes.

Consulte http://www.ibm.com/developerworks/java/library/j-jtp05273.html para obtener una buena descripción general.

Debería intentar implementar el código hash para que diferentes objetos den diferentes resultados. No creo que haya una forma estándar de hacer esto.

Lee este artículo para obtener información .

Un hashcode es útil para almacenar un objeto en una colección, como un hashset. Al permitir que un objeto defina un Hashcode como algo único, permite que el algoritmo del HashSet funcione de manera efectiva.

El objeto mismo usa la dirección del objeto en la memoria, que es muy única, pero puede no ser muy útil si dos objetos diferentes (por ejemplo, dos cadenas idénticas) se deben considerar iguales, incluso si están duplicados en la memoria.

Dos objetos con código hash diferente no deben ser iguales con respecto a iguales ()

a.hashCode() != b.hashCode() debe implicar !a.equals(b)

Sin embargo, dos objetos que no son iguales con respecto a iguales () pueden tener el mismo código hash. Almacenar estos objetos en un conjunto o mapa será menos eficiente si muchos objetos tienen el mismo código hash.

Realmente no es una respuesta, sino que se agrega a mi comentario anterior

no se puede garantizar que la dirección interna del objeto permanezca sin cambios en la JVM, cuyo recolector de basura podría moverla durante la compactación en stack.

Traté de hacer algo como esto:

 public static void main(String[] args) { final Object object = new Object(); while (true) { int hash = object.hashCode(); int x = 0; Runtime r = Runtime.getRuntime(); List list = new LinkedList(); while (r.freeMemory() / (double) r.totalMemory() > 0.3) { Object p = new Object(); list.add(p); x += object.hashCode();//ensure optimizer or JIT won't remove this } System.out.println(x); list.clear(); r.gc(); if (object.hashCode() != hash) { System.out.println("Voila!"); break; } } } 

Pero el código hash realmente no cambia … ¿alguien puede decirme cómo el JDK de Sun realmente implementa Obect.hashcode?

devuelve un número hexadecimal de 6 dígitos. Esta suele ser la ubicación de la memoria de la ranura donde se dirige el objeto. Desde un algoritmo per se, supongo que JDK hace doble hashing (implementación nativa) que es una de las mejores funciones hash para el direccionamiento abierto. Este esquema de doble hash reduce altamente la posibilidad de colisiones.

La siguiente publicación dará una idea de apoyo:

Java: confusión de HashMap sobre el manejo de colisiones y el método get ()

Debe anular hashCode en cada clase que anule equals. De lo contrario, se producirá una infracción del contrato general de Object.hashCode, que impedirá que su clase funcione correctamente conjunction with all hash-based collection , including HashMap, HashSet, and Hashtable.