Todos sabemos que el lenguaje Java está completamente orientado a objetos. En Java, todos los objetos se heredan de la clase de objeto.
El método igual compara las direcciones señaladas por referencias de dos objetos. HashCode es un método local, que devuelve el valor de la dirección de objeto. Hay dos métodos en la clase OJBect iguales y hashcode. Estos dos métodos se utilizan para comparar si los dos objetos son iguales.
¿Por qué tenemos que anular el método hashcode mientras reescribe el método igual?
Se puede entender de la siguiente manera: después de reescribir el método igual, la lógica comercial para juzgar la igualdad de objetos cambiará. El diseñador de la clase no quiere comparar la igualdad de dos objetos comparando la dirección de memoria. No tiene sentido continuar comparando de acuerdo con la dirección. Entonces, simplemente se cambia juntos.
Otra razón proviene de colecciones. Hablemos de ello lentamente debajo ~
Por ejemplo:
En la escuela, es a través de la identificación del estudiante determinar si esta persona pertenece.
El escenario en el código a continuación es la entrada de registro del estudiante, el estudiante número 123 se asigna al estudiante Tom, el número 456 del estudiante se asigna al estudiante Jerry y el número 123 del estudiante se asigna a Lily por error. Sin embargo, el mismo número de estudiante no debe ocurrir durante el proceso de inscripción del estado del estudiante.
Dependiendo de los requisitos situacionales, los objetos duplicados no se pueden agregar y se pueden implementar a través de Hashset.
Prueba de clase pública {public static void main (string [] args) {Student stu = new Student (123, "Tom"); Hashset <estudiante> set = new Hashset <> (); set.add (stu); set.add (new student (456, "jerry"); set.add (new student (123, "Lily")); iterator <itherator <termator = setator (set.Iterator (); while (iterator.hasNext ()) {Student Student = Iterator.Next (); System.out.println (student.getStunum () + "---" + student.getName ());}}}; class Student {private int stunum; private string name; public student (int stunum, string name) {this.stunum = stunum; this.name = name;} public int nombre;}@overridePublic boolean iguales (object obj) {if (this == obj) return true; if (obj instancef student) {if (this.getStunum () == ((estudiante) obj) .getStunum ()) return true;} return false;}} La salida es:
123 --- lirio
456 --- Jerry
123 --- Tom
Según la salida, descubrimos que la asignación del estudiante número 123 a Lily nuevamente tuvo éxito. ¿Qué salió mal?
Echemos un vistazo al método Agregar de hashset:
public boolean add (e e) {return map.put (e, presente) == null;} De hecho, Hashset se implementa a través de HashMap, por lo que rastreamos el método PUT de HashMap:
public v put (k key, v value) {if (table == vacía_table) {inflateTable (umbral);} if (key == null) return putfornullkey (valor); int hash = hash (key); int i = indexfor (hash, table.length); para (entrada <k, v> e = table [i]; e! = null; e = ext) hash && (((k = e.key) == clave || key.equals (k)))) {v OldValue = e.Value; e.Value = valor; e.RecordAccess (this); return OldValue;}} modcount ++; Addentry (hash, clave, valor, i); return null;}1. Según la clave, es decir, el objeto que se agregará por hashset, obtenga el CODEDE y el CODEDE se usa para realizar operaciones de bits específicas para obtener el código hash;
2. Use el posicionamiento de código hash para encontrar el subíndice de matriz para obtener el encabezado de enlace de la lista vinculada;
3. Traver la lista vinculada para averiguar si hay la misma clave. La base para el juicio es E.Hash == Hash && ((k = E.Key) == Key || Key.equals (k)). Al agregar lirio, debido a que el método igual se reescribe, la segunda condición debe ser cierta al atravesar Tom; Pero debido a que el método hashcode todavía usa la clase principal, el húsico de Tom y Lily es diferente, es decir, el código hash es diferente y la primera condición es falsa. Aquí obtenemos que los dos objetos son diferentes, por lo que Hashset agrega a Lily con éxito.
La razón es que el método hashcode no está reescribiendo. Aquí hay una modificación:
Prueba de clase pública {public static void main (string [] args) {Student stu = new Student (123, "Tom"); Hashset <estudiante> set = new Hashset <> (); set.add (stu); set.add (new student (456, "jerry"); set.add (new student (123, "Lily")); iterator <itherator <termator = setator (set.Iterator (); while (iterator.hasNext ()) {Student Student = Iterator.Next (); System.out.println (student.getStunum () + "---" + student.getName ());}}}; class Student {private int stunum; private string name; public student (int stunum, string name) {this.stunum = stunum; this.name = name;} public int nombre;}@overridePublic boolean iguales (object obj) {if (this == obj) return true; if (obj instancef student) {if (this.getStunum () == ((student) obj) .getStunum ()) return true;} return false;}@overDepublic int Hashcode () {return getStunum ();}} Producción:
456 --- Jerry
123 --- Tom
Reescribe el método hashcode y devuelve el número de alumno. Ok, está hecho.
Algunas personas pueden preguntarse, E.Hash == Hash && ((k = E.Key) == Key || Key.equals (k)) es un poco complicado? Creo que es suficiente para usar el método igual. ¿Por qué necesitas juzgar hashcode de una vez?
Porque al atravesar y juzgar en la estructura de la lista vinculada de HASHMAP, la lógica comercial del método reescrito igual es más complicado para comparar si los objetos son iguales en situaciones específicas, y la lógica comercial de la bucle hacia abajo afectará la eficiencia de búsqueda. Así que aquí ponemos el juicio de hashcode primero. Mientras el hashcode no sea igual, terminará de jugar, y ya no hay necesidad de llamar a los iguales complejos. Mejorar la eficiencia de HASHMAP en gran medida.
Por lo tanto, el método hashcode es permitirnos usar clases de recolección como el hashmap normalmente, porque hashmap determina si los objetos son iguales, tanto hashcode como igual a la comparación. Esta implementación es para mejorar la eficiencia de HASHMAP.