Prefacio
Como todos sabemos, java.lang.object tiene un método hashcode () y igual (), que juega un papel importante en el diseño de software. Reescribe estos dos métodos en algunas clases para lograr algunas funciones importantes.
1. ¿Por qué usar 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?
Algunas personas dicen: Object.equal() por supuesto, se usa para comparar si los objetos son iguales. 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 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 este 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.
Esta es también la razón por la cual cuando el conjunto establece datos de tipo de objeto almacena, es necesario no solo reescribir el método hashcode () del objeto sino también reescribir el método igual ().
2. ¿Cómo usar hashcode ()?
La relación entre el valor de retorno de hashcode () y igual ()
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; @Override public boolean iguales (objeto obj) {if (obj == this) 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; }}Los métodos Equals () y HashCode () se utilizan para compararse en la misma clase, especialmente cuando almacenan el mismo objeto de clase en el contenedor, como SET para almacenar objetos en la misma clase.
Aquí primero tenemos que entender un problema:
Dos objetos con igual () iguales, hashcode () deben ser iguales, y dos objetos con igual () no iguales, no pueden probar que su hashcode () no es igual. En otras palabras, para dos objetos cuyo método igual () no es igual, hashcode () puede ser igual.
Aquí hashcode es como el índice de cada personaje en el diccionario, y igual () es como comparar diferentes palabras bajo el mismo carácter en el diccionario. Al igual que en el diccionario, la búsqueda de las dos palabras "yo" y "espontáneas" bajo la palabra "yo" en el diccionario, si es igual () para determinar la igualdad de la consulta de palabras, es la misma palabra. Por ejemplo, las dos palabras en comparación con igual () son "self", entonces los valores obtenidos por el método hashcode () deben ser iguales en este momento; Si el método igual () compara las palabras "self" y "espontánea", entonces el resultado es que no desea esperar, pero ambas palabras pertenecen a las palabras "yo" y, al buscar índices, es decir, hashcode () es el mismo. Si iguales () compara las palabras "self" y "ellos", entonces los resultados también son diferentes, y los resultados obtenidos por hashcode () también son diferentes en este momento.
Por el contrario: hashcode () es diferente, y es igual () se puede introducir; hashcode () es igual, igual () puede ser igual o no ser igual.
En la clase de objeto, el método hashcode () es un método local, que devuelve el valor de dirección del objeto. El método igual () en la clase de objeto también compara los valores de dirección de los dos objetos. Si es igual () es igual, significa que los valores de dirección de los dos objetos también son iguales. Por supuesto, hashcode () es igual.
Dado que iguales es más preciso para comparar elementos iguales, ¿por qué usar el método hashcode ()?
Debido a que el algoritmo hash proporciona una alta eficiencia para encontrar elementos, si desea encontrar si una colección contiene un objeto, ¿cómo escribir el código de programa aproximado?
Por lo general, elimina cada elemento uno por uno para comparar con el objeto que está buscando. Cuando encuentre que el resultado de la comparación de métodos iguales entre un elemento y el objeto que está buscando, deje de buscar y devuelva información positiva. De lo contrario, devuelva información negativa. Si hay muchos elementos en una colección, como 10,000 elementos y no contienen el objeto que está buscando, significa que su programa necesita eliminar 10,000 elementos de la colección y comparar uno por uno para llegar a una conclusión.
La clase de objeto define un método hashcode () para devolver el código hash de cada objeto Java. Al buscar un objeto de la colección HashSet, el sistema Java primero llama al método hashcode () del objeto para obtener la tabla de código hash del objeto, y luego encuentra el área de almacenamiento correspondiente en función del hash, y finalmente obtiene cada elemento en el área de almacenamiento y la compara con el método de objetos para igual. De esta manera, puede obtener la conclusión sin atravesar todos los elementos de la colección. Se puede ver que la colección Hashset tiene un buen rendimiento de recuperación de objetos.
Sin embargo, la eficiencia del almacenamiento de objetos en la colección Hashset es relativamente baja, porque al agregar un objeto a la colección hashset, el código hash del objeto debe calcularse primero y la ubicación de almacenamiento del objeto en la colección se determina en función de este código hash. Para garantizar que los objetos de instancia de una clase se puedan almacenar normalmente en hashset, los resultados de los dos objetos de instancia de esta clase deben ser iguales en comparación con el método igual () son iguales; Es decir, si el resultado de obj1.equals(obj2) es verdadero, entonces el resultado de la siguiente expresión también debe ser true:obj1.hashCode() == obj2.hashCode() .
En otras palabras: cuando reescribimos el método igual de un objeto, debemos reescribir su método hashcode. Si no reescribimos su método hashcode, el método hashcode en el objeto objeto siempre devuelve la dirección hash de un objeto, y esta dirección nunca es igual. Entonces, incluso si el método igual se reescribe en este momento, no habrá ningún efecto específico, porque si el método hashcode no quiere esperar, no llamará al método igual para la comparación, por lo que no tiene sentido.
La mayoría de las estructuras de datos utilizan el método igual para determinar si contienen un elemento, por ejemplo:
List <String> list = arrays.aslist ("a", "b", "c"); boolean contiene = list.contains ("b"); Esta variable contiene el resultado es verdadero porque, aunque "B" son instancias diferentes (además, se ignora la residencia de cadena), son iguales.
Utilizan una forma rápida de comparar (reducir la igualdad de instancia potencial) en lugar de comparar cada elemento contenido en la instancia. La comparación rápida solo requiere comparar los siguientes aspectos:
La comparación de acceso directo significa que al comparar los valores hash, puede reemplazar una instancia con un valor entero. Las instancias con el mismo código hash no son necesariamente iguales, pero las instancias con igualdad deben tener el mismo valor hash. (o debería haberlo hecho, discutiremos esto pronto) Estas estructuras de datos a menudo son nombradas por esta técnica, y pueden ser identificadas por hash, entre los cuales hashmap es el representante más famoso.
Suelen funcionar así:
Al agregar un elemento, su código hash se usa para calcular el índice de la matriz interna (es decir, el llamado cubo)
En caso afirmativo, los elementos desiguales tienen el mismo código hash, terminan en el mismo cubo y se agrupan, por ejemplo, agregando a la lista.
Cuando se realiza una instancia contiene operaciones, su código hash se utilizará para calcular el valor del cubo (valor del índice), y la instancia se comparará solo cuando los elementos existan en el valor del índice correspondiente.
Por lo tanto, es igual, hashcode se define en la clase de objeto.
Si hashcode se usa como un atajo para determinar la igualdad, entonces solo hay una cosa que debemos importarnos: los objetos iguales deben tener el mismo hashcode, por lo que si anulamos el método igual, ¡tenemos que crear una implementación de hashcode que lo coincida!
De lo contrario, los objetos iguales pueden no tener el mismo código hash, porque llamarán a la implementación predeterminada de Object.
Cita de documentos oficiales
Convención general hashcode:
Al llamar al mismo objeto que se ejecuta en una aplicación Java, el método hashcode siempre debe devolver el mismo número entero. Este entero no necesita ser consistente en diferentes aplicaciones Java. De acuerdo con equals(Object) , si dos objetos son iguales, los dos objetos llaman al método hashcode deben producir el mismo resultado.
De acuerdo con equals(Object) , si los dos objetos no son iguales, entonces llamar al método hashcode no necesariamente produce diferentes resultados enteros. Sin embargo, los programadores deben darse cuenta de que producir diferentes resultados enteros para objetos desiguales probablemente mejorará el rendimiento de la tabla hash.
Implementación de hashcode
Aquí hay una implementación simple de person.hashcode() :
@OverridePublic int hashcode () {return Objects.hash (FirstName, LastName);}La persona calcula el código hash combinando múltiples campos. Todos están calculados por la función hash de objeto.
Seleccione un campo
¿Pero qué campos están relacionados? Los requisitos nos ayudarán a responder esta pregunta:
Si un objeto igual que debe tener el mismo código hash, el código hash calculado no debe incluir ningún campo que no se use para las verificaciones de igualdad. (De lo contrario, los dos objetos son solo que estos campos son diferentes, pero aún pueden ser iguales, pero los códigos hash de los dos objetos serán diferentes en este momento). Por lo tanto, el subconjunto de los campos utilizados cuando los campos de grupo hash deberían ser iguales. Los mismos campos se usan por defecto, pero hay algunos detalles a considerar.
Resumir
Entendemos que calcular el código hash es comprimir un valor entero igual: los objetos iguales deben tener el mismo código hash, y para las consideraciones de rendimiento, es mejor compartir el mismo código hash tan pocos como posibles objetos desiguales.
Esto significa que si el método igual se reescribe, entonces el método hashcode debe reescribirse.
Al implementar hashcode, usa los mismos campos que se usan en igual (o un subconjunto de campos utilizados en iguales)
Es mejor no incluir campos mutables. No considere llamar a hashcode para colecciones. Si no hay un modo específico de entrada especial, intente usar un algoritmo de hash general.
De acuerdo, lo anterior es todo el contenido de este artículo. Espero que el contenido de este artículo tenga cierto valor de referencia para el estudio o el trabajo de todos. Si tiene alguna pregunta, puede dejar un mensaje para comunicarse. Gracias por su apoyo a Wulin.com.