JavaRush /Blog Java /Random-ES /Sobrecarga de los métodos equals() y hashCode() en Java
Coder
Nivel 17

Sobrecarga de los métodos equals() y hashCode() en Java

Publicado en el grupo Random-ES

Anulando los métodos equals() y hashCode() en Java

Equalsy hashCodeson los métodos fundamentales declarados en la clase Objecty contenidos en las bibliotecas estándar de Java. Sobrecarga de los métodos equals() y hashCode() en Java - 1El método еquals()se utiliza para comparar objetos y hashCodegenerar un código entero para el objeto. Estos métodos se utilizan ampliamente en las bibliotecas estándar de Java al insertar y recuperar objetos en formato HashMap. El método equaltambién se utiliza para garantizar que solo se almacenen objetos únicos en HashSetotras Setimplementaciones, así como en cualquier otro caso en el que sea necesario comparar objetos. La implementación predeterminada del método equals()en la clase java.lang.Objectcompara referencias a las direcciones de memoria que almacenan las variables y devuelve truesolo si las direcciones coinciden, en otras palabras, las variables se refieren al mismo objeto. Java recomienda anular los métodos equals()y hashCode()si espera que la comparación se realice según la lógica natural o la lógica empresarial. Muchas clases en las bibliotecas estándar de Java los anulan, por ejemplo, la clase Stringanula equalspara que devuelva truesi el contenido de los dos objetos que se comparan es el mismo. La clase contenedora anula Integerel método equalpara realizar una comparación numérica, y así sucesivamente. Dado que Java HashMaptambién se basa en métodos y para comparar sus y , Java ofrece las siguientes reglas para anular estos métodos: HashTableequals()hashCode()keyvalues
  1. Reflexividad: El objeto debe ser igual a sí mismo.
  2. Simétrico: si a.equals(b)devuelve true, entonces b.equals(a)también debe devolver true.
  3. Transitividad: si a.equals(b)regresa truey b.equals(c)también regresa true, entonces c.equals(a)también debe regresar true.
  4. Consistencia: las llamadas repetidas a un método equals()deben devolver el mismo valor siempre que no se cambien algunos de los valores de propiedad del objeto. Es decir, si dos objetos son iguales en Java, serán iguales siempre que sus propiedades permanezcan sin cambios.
  5. Comparación null: Se debe comprobar el objeto null. Si el objeto es igual a null, entonces el método debería devolver false, no NullPointerException. Por ejemplo, a.equals(null)debería devolver false.

Acuerdo entre iguales y hashCode en Java

  1. Si los objetos son iguales en los resultados de la ejecución del método equals, entonces hashcodedeben ser iguales.
  2. Si los objetos no son iguales en los resultados de la ejecución del método equals, entonces hashcodepueden ser iguales o diferentes. Sin embargo, para mejorar el rendimiento, es mejor que diferentes objetos devuelvan códigos diferentes.

Cómo anular el método igual en Java

  1. @Override
    public boolean equals(Object obj) {
    /*1. Controlar*/if (obj == this) {
    /*y volver */ return true;
             }
  2. Проверьте un objeto на null, а также проверьте, чтобы un objetoы были одного типа. Не делайте проверку с помощью instanceof так Cómo такая проверка будет возвращать true для подклассов и будет работать правильно только в случае если ваш класс объявлен Cómo immutable. Вместо этого можно использовать getClass();

    if (obj == null || obj.getClass() != this.getClass()) {
                return false;
    }
  3. Объявите переменную типа, который вы сравниваете, и приведите obj к этому типу. Потом сравнивайте каждый атрибут типа начиная с численных атрибутов (если имеются) потому что численные атрибуты проверяются быстрей. Сравнивайте атрибуты с помощью операторов И и ИЛИ (так называемые short-circuit logical operators) для объединения проверок с другими атрибутами.

    Person guest = (Person) obj;
            return id == guest.id && (firstName == guest.firstName ||
                (firstName != null && firstName.equals(guest.getFirstName())))
                    && (lastName == guest.lastName || (lastName != null &&                      lastName .equals(guest.getLastName())));
    }
Полный пример переопределения метода equals в Java
/** * Person class with equals and hashcode implementation in Java * @author Javin Paul */
public class Person {
    private int id;
    private String firstName;
    private String lastName;

    public int getId() { return id; }
    public void setId(int id) { this.id = id;}

    public String getFirstName() { return firstName; }
    public void setFirstName(String firstName) { this.firstName = firstName; }
    public String getLastName() { return lastName; }
    public void setLastName(String lastName) { this.lastName = lastName; }
    @Override
    public boolean equals(Object obj) {
    if (obj == this) {
        return true;
    }
    if (obj == null || obj.getClass() != this.getClass()) {
        return false;
    }

    Person guest = (Person) obj;
    return id == guest.id
        && (firstName == guest.firstName
            || (firstName != null &&firstName.equals(guest.getFirstName())))        && (lastName == guest.lastName
            || (lastName != null && lastName .equals(guest.getLastName())
            ));
    }
    @Override
    public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((firstName == null) ? 0 : firstName.hashCode());             result = prime * result + id; result = prime * result +
        ((lastName == null) ? 0 : lastName.hashCode()); return result;
    }
 }

Распространенные ошибки при переопределении equals в Java

  1. Вместо того, чтобы переопределять метод equals (Override) программист перегружает его (Overload)Синтаксис метода equals() в классе Object определен Cómo public boolean equals(Object obj), но многие программисты ненароком перегружают метод: public boolean equals(Person obj) - en lugar de Object в качестве аргумента используют Nombre своего класса (напр. Person). Эту ошибку сложно обнаружить из-за static binding. Таким образом, если вы вызовете этот метод для un objetoа своего класса, то метод не просто скомпoруется, а даже сделает это корректно. Однако, если вы положите ваш un objeto в коллекцию, например ArrayList и вызовете метод contains(), работа которого основана на методе equals(), то метод contains не сможет обнаружить ваш un objeto.

  2. При переопределении метода equals() не проверять на null переменные, что в конечном итоге заканчивается NullPointerException при вызове equals(). Ниже представлен корректный código.

    firstname == guest.firstname || (firstname != null &&
         firstname.equals(guest.firstname));
  3. Третья распространенная ошибка это не переопределять метод hashCode(), а только equals(). Вы обязаны переопределять оба метода equals() и hashCode() в Java. Метод hashCode используется в hash -коллекциях(например HashSet), и чем меньше будет коллизий (одинаковый código при разных un objetoах) тем эффективнее эти коллекции будут работать с un objetoами вашего класса.

  4. Последняя распространенная ошибка программистов в том, что при переопределении метода equals() не сохраняется соответствие между методами equals() и compareTo(), что является неформальным требованием для избежания хранения дубликатов в Set (SortedSet, TreeSet).

Подсказки Cómo писать в Java метод equals

  1. Большинство IDE такие Cómo NetBeans, Eclipse и IntelliJ IDEA обеспечивают поддержку генерации методов equals() и hashCode(). В Eclipse нажмите правую кнопку -> source -> generate equals() и hashCode().

  2. Если в классе есть уникальный бизнес-ключ, то будет достаточно сделать проверку только на es igualство этих полей. Как в нашем примере “id” - уникальный номер для каждого Person.

  3. При переопределении hashCode() в Java удостоверьтесь в использовании всех полей, что были использованы в методе equals().

  4. Stringy clases contenedoras como Integery anulan el método , pero no anulan.FloatDoubleequals()StringBuffer

  5. Siempre que sea posible, cree campos immutableusando finalvariables en Java.

  6. Al comparar Stringobjetos, utilice equals()el operador .en su lugar ==.

  7. Dos objetos que son lógicamente iguales pero cargados desde objetos diferentes ClassLoaderno pueden ser iguales. Recuerde que consultar con getClass()volverá falsesi la clase del cargador es diferente.

  8. Utilice @Overridela anotación también en el método . hashCode, ya que esto evita errores sutiles como el valor de retorno del método int.Sin embargo, algunos programadores devuelven long.

PD ¡Queridos colegas! ¡Este artículo me resultó útil para resolver problemas de nivel 21! Te deseo mucha suerte en el análisis de este tema, ¡usa la traducción! Espero que me ayuden a subir mi calificación, ya que ahora ni siquiera puedo dejar un comentario en este foro. ¡Muchas gracias a todos! Artículo original omití algunos puntos por falta de tiempo libre, pero traduje todo lo que necesitas saber para resolver problemas del nivel 21.
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION