1. ¿Por qué hashcode ()?
Los elementos en el conjunto de conjuntos son desordenados e irrepetibles, entonces, ¿cuál es la base para juzgar si se repiten dos elementos? "Por supuesto, Object.Equal () se usa para comparar si los objetos son iguales", dijo un cierto APE. Sin embargo, hay una gran cantidad de objetos en el conjunto, y el número de comparaciones de los elementos de objeto agregados al conjunto establecido aumentará gradualmente, reduciendo en gran medida la eficiencia de la operación del programa. Java usa algoritmo de hash (también llamado algoritmo de hash) para resolver este problema. El objeto (o datos) se asigna directamente a una dirección de acuerdo con un algoritmo específico, y la eficiencia de acceso del objeto mejora enormemente. De esta manera, cuando un conjunto de conjuntos que contiene una gran cantidad de elementos necesita agregar un elemento (objeto), primero llame al hashcode () de este elemento, y puede colocar la ubicación de almacenamiento real de este elemento a la vez. Si no hay elemento en esta posición, significa que el objeto se almacena en el conjunto de colección por primera vez, y el objeto se almacena directamente en esta posición; Si hay un objeto en esta posición, llame a igual () para ver si los dos objetos son iguales. Si lo mismo es verdadero, descarte el elemento y no existe. Si no es igual, hash a otras direcciones.
2. ¿Cómo usar hashcode ()?
Java Language tiene cinco requisitos que deben seguirse para igual () en el diseño APE.
simetría. Si A.Equal (b) devuelve "verdadero", entonces B.Equal (a) también debe devolver "verdadero".
Pensativo. A.Equal (a) debe devolver "verdadero".
Transitivo. Si a.equal (b) devuelve "verdadero" y b.equal (c) devuelve "verdadero", entonces c.equal (a) debe devolver "verdadero".
consistencia. Si A.Equal (b) devuelve "verdadero", siempre que el contenido de A y B permanezcan sin cambios, sin importar cuántas veces A.Equal (b) debe devolver "verdadero".
En cualquier caso, A.Equals (NULL) siempre devuelve "falso"; A.Equals (objetos de diferentes tipos y a) siempre devuelve "falso".
La relación entre el valor de retorno de hashcode () y igual ().
Si A.Equals (b) devuelve "verdadero", entonces el hashcode () de A y B debe ser igual.
Si A.Equals (b) devuelve "falso", entonces el hashcode () de A y B puede ser igual o puede ser desigual.
Aquí hay un ejemplo. En el desarrollo real de software, es mejor reescribir estos dos métodos.
Empleado de clase pública {int EmployeEd; Nombre de cadena; // Otros métodos estarían aquí @Override public boolean iguales (object obj) {if (obj ==) return true; Empleado emp = (empleado) obj; if (EmployeeId.equals (emp.getEmloyeeId ()) && name == emp.getName ()) return true; devolver falso; } @Override public int hashcode () {int hash = 1; hash = hash * 17 + EmployeeId; hash = hash * 31 + name.hashcode (); regresar hash; }}3. El siguiente es un enfoque en el método de implementación hashcode () de las clases de uso común.
HASCODE () de la clase de cadena
public int hashcode () {int h = hash; if (h == 0) {int off = offset; char val [] = valor; int len = count; para (int i = 0; i <len; i ++) {H = 31*H+val [Off ++]; } hash = h; } return h; }Lo más interesante de este código es el método de implementación de hash. El valor de hash calculado final es:
S [0] 31N-1 + S [1] 31N-2 + ... + S [N-1]
S [i] es el carácter i-th de una cadena, y N es la longitud de una cadena. Entonces, ¿por qué usar 31 aquí en lugar de otros números?
31 es un número primo impar. Si el multiplicador es un número uniforme y la multiplicación se desborda, la información se perderá porque la multiplicación con 2 es equivalente a la operación de cambio. Los beneficios del uso de números primos no son obvios, pero los resultados del hash se utilizan convencionalmente para calcular los resultados hash. 31 tiene una buena característica, que es usar el cambio y la resta en lugar de la multiplicación para obtener un mejor rendimiento: 31*i == (i << 5) -i. Las máquinas virtuales pueden completar automáticamente esta optimización. (De Java efectivo)
HASCODE () de la clase de objeto
hashcode () es un método nativo en la clase de objeto. ¿Cómo llamar a los métodos nativos?
público nativo int hashcode ();
La clase de método nativo de la clase de objeto se puede encontrar aquí. Lea otro blog para un análisis en profundidad
Métodos static jninativemethod [] = {{"hashcode", "() i", (void *) & jvm_ihashcode}, {"espera", "(j) v", (void *) & jvm_monitorwait}, {"notificar", "() v", (void *) y jvm_monitroToTify}, {notify "() V", (void *) & jvm_monitornotifyall}, {"clone", "() ljava/lang/object;", (void *) & jvm_clone},};El código fuente incluye getClass () (ver Line58), etc. HashCode () (ver Line43) se define como un puntero a JVM_IHASHCODE.
JVM.CPP Define la función JVM_IHASHCODE (línea 504). Esta función llama ObjectSynCronizer :: FastHashCode, que se determina en SynCronizer.cpp. Para la implementación de FastHashCode en la línea 576 y get_next_hash en la línea 530, puede consultar la implementación de fasthashcode en la línea 576 y get_next_hash en la línea 530.