¿Por qué necesito reescribir hashCode cuando uso equals y reescribiendo el método equals?

1. El uso de iguales

Se utiliza para determinar si dos objetos son iguales.

  • Si la clase no anula el método equals de Object, llame al método equals de Object para comparar si las direcciones de los objetos en el montón son iguales
  • Si la clase anula el método equals, generalmente se usa para comparar si las propiedades del objeto son iguales
2. ¿Por qué reescribir iguales?

¿Por qué reescribir el método de iguales? Depende principalmente del escenario de uso, si no necesita comparar objetos, no necesita reescribir.
Por ejemplo, si el usuario desea modificar el nombre de usuario, se pasa un objeto Usuario. En este momento, el objeto Usuario antiguo se recupera de la base de datos y los dos se comparan si son iguales (de hecho, el nombre de usuario Si el método equals no se reescribe, el método equals de Object se utiliza para comparar las direcciones de los objetos, lo cual es contrario a nuestros deseos.

Ejemplo 1

public class Main {
    
    
    public static void main(String[] args) {
    
    
        User newUser = new User("dkangel");
        User dbUser = new User("dkangel");
        System.out.println(newUser.equals(dbUser));
    }
}

1. El método equals no se anula, el resultado es falso

public class User {
    
    
    private String name;
    
    public User(String name) {
    
    
        this.name = name;
    }
    
    public String getName() {
    
    
        return name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }
}

2. Anula el método de igualdad, el resultado es verdadero.

public class User {
    
    
    private String name;

    public User(String name) {
    
    
        this.name = name;
    }

    public String getName() {
    
    
        return name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }

    /**
     * 重写equals方法,比较name属性是否相等
     *
     * @param obj 待比较对象
     * @return boolean
     */
    @Override
    public boolean equals(Object obj) {
    
    
        if (this == obj) {
    
    
            return true;
        }
        if (!(obj instanceof User)) {
    
    
            return false;
        }
        User user = (User) obj;
        return Objects.equals(user.name, this.getName());
    }
}
3. ¿Reescribir el método equals debe reescribir el método hashCode? ¿Por qué?

La función del método hashCode es obtener un código hash (también conocido como código hash) y la función del código hash es determinar la posición del objeto en la tabla hash.

Primero observe las disposiciones relevantes de hashCode y equals

  • Si los dos objetos son iguales, el código hash también debe ser el mismo
  • Los dos objetos son iguales, y el método equals en los dos objetos, respectivamente, devuelve verdadero
  • Dos objetos tienen el mismo valor de código hash, no son necesariamente iguales
  • El comportamiento predeterminado del método hashCode es generar valores únicos para los objetos en el montón. Si el método hashCode no se anula, los dos objetos de esta clase no serán iguales de todos modos (incluso si los dos objetos apuntan a los mismos datos)

Desde el punto de vista de la convención: reescribir el método equals debe reescribir el método hashCode.

Desde el punto de vista de uso:

  • Si la clase no necesita crear una tabla hash correspondiente a la clase durante el uso (es decir, no se usará en los datos que usan hash como HashMap / HashSet / HashTable), entonces no tiene nada que ver con el hashCode, y no necesita reescribir el método hashCode. Como en el ejemplo 1 anterior, solo se reescribe el método equals y no se reescribe el método hashCode, lo que no afecta el uso.

  • Si la clase necesita crear una tabla hash correspondiente a la clase durante el uso, entonces el método hashCode necesita ser reescrito. Dale otra castaña

Ejemplo 2

Cuando agrega un objeto a un HashSet, HashSet primero calculará el valor del código hash del objeto para determinar la posición donde se agrega el objeto, y también lo comparará con los valores del código hash de otros objetos agregados en esa posición. Si no hay coincidencia hashcode, HashSet asumirá el objeto No recurrencia. Pero si se encuentra un objeto con el mismo valor de código hash, se llamará al método equals () para verificar si los objetos con el mismo código hash son realmente iguales. Si los dos son iguales, HashSet no permitirá que se una a la operación con éxito. Si son diferentes, se cambiarán a otra ubicación.

public class Main {
    
    
    public static void main(String[] args) {
    
    
        User newUser = new User("dkangel");
        User dbUser = new User("dkangel");
        User otherUser = new User("zhangsan");

        HashSet<User> users = new HashSet();
        users.add(newUser);
        users.add(dbUser);
        users.add(otherUser);

        System.out.println("users size: " + users.size());
        users.forEach(user -> System.out.printf("name: %s, hashCode: %s\n", user.getName(), user.hashCode()));
    }
}

1. El método hashCode no se reescribe
结果为3 y los dos objetos cuyo nombre es "dkangel" no han reescrito el método hashCode, lo que da como resultado valores duplicados en el conjunto.
Inserte la descripción de la imagen aquí
2. Vuelva a escribir el método hashCode

public class User {
    
    
    private String name;

    public User(String name) {
    
    
        this.name = name;
    }

    public String getName() {
    
    
        return name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }

    @Override
    public boolean equals(Object obj) {
    
    
        if (this == obj) {
    
    
            return true;
        }
        if (!(obj instanceof User)) {
    
    
            return false;
        }
        User user = (User) obj;
        return Objects.equals(user.name, this.getName());
    }

    @Override
    public int hashCode() {
    
    
        return this.name.hashCode();
    }
}

结果为2, Reescribe el método hashCode. Dos objetos llamados "dkangel" solo agregan uno al conjunto.
Inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/Dkangel/article/details/105980473
Recomendado
Clasificación