JavaRush /Blog Java /Random-FR /Surcharge des méthodes equals() et hashCode() en Java
Coder
Niveau 17

Surcharge des méthodes equals() et hashCode() en Java

Publié dans le groupe Random-FR

Remplacement des méthodes equals() et hashCode() en Java

Equalset hashCodesont les méthodes fondamentales déclarées dans la classe Objectet contenues dans les bibliothèques Java standard. Surcharge des méthodes equals() et hashCode() en Java - 1La méthode еquals()est utilisée pour comparer des objets et hashCodegénérer un code entier pour l'objet. Ces méthodes sont largement utilisées dans les bibliothèques standard Java lors de l'insertion et de la récupération d'objets dans HashMap. La méthode equalest également utilisée pour garantir que seuls les objets uniques sont stockés dans HashSetd'autres Setimplémentations, ainsi que dans tout autre cas où des objets doivent être comparés. L'implémentation par défaut de la méthode equals()dans la classe java.lang.Objectcompare les références aux adresses mémoire stockées par les variables et ne renvoie trueque si les adresses correspondent, en d'autres termes, les variables font référence au même objet. Java recommande de remplacer les méthodes equals()et hashCode()si vous souhaitez que la comparaison soit effectuée selon la logique naturelle ou la logique métier. De nombreuses classes dans les bibliothèques Java standard les remplacent, par exemple la classe Stringles remplace equalsafin qu'elle soit renvoyée truesi le contenu des deux objets comparés est le même. La classe wrapper remplace Integerla méthode equalpour effectuer une comparaison numérique, et ainsi de suite. Étant donné que Java s'appuie HashMapégalement sur les méthodes and pour comparer leurs and , Java propose les règles suivantes pour remplacer ces méthodes : HashTableequals()hashCode()keyvalues
  1. Réflexivité : L'objet doit être égal à lui-même.
  2. Symétrique : s'il a.equals(b)renvoie true, alors b.equals(a)il doit également renvoyer true.
  3. Transitivité : si a.equals(b)elle renvoie trueet b.equals(c)renvoie également true, alors c.equals(a)elle doit également renvoyer true.
  4. Cohérence : les appels répétés à une méthode equals()doivent renvoyer la même valeur tant que certaines valeurs de propriétés de l'objet ne sont pas modifiées. Autrement dit, si deux objets sont égaux en Java, ils le seront tant que leurs propriétés restent inchangées.
  5. Comparaison null: L'objet doit être vérifié null. Si l'objet est égal à null, alors la méthode doit renvoyer false, et non NullPointerException. Par exemple, a.equals(null)il devrait renvoyer false.

Accord entre égaux et hashCode en Java

  1. Si les objets sont égaux dans les résultats de l’exécution de la méthode equals, alors ils hashcodedoivent être identiques.
  2. Si les objets ne sont pas égaux dans les résultats de l’exécution de la méthode equals, ils hashcodepeuvent alors être identiques ou différents. Cependant, pour améliorer les performances, il est préférable que différents objets renvoient des codes différents.

Как переопределять метод equals в Java

  1. @Override
    public boolean equals(Object obj) {
    /*1. Check*/if (obj == this) {
    /*and return */ return true;
             }
  2. Проверьте an object на null, а также проверьте, чтобы an objectы были одного типа. Не делайте проверку с помощью instanceof так How такая проверка будет возвращать true для подклассов и будет работать правильно только в случае если ваш класс объявлен How 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 определен How public boolean equals(Object obj), но многие программисты ненароком перегружают метод: public boolean equals(Person obj) - instead of Object в качестве аргумента используют Name своего класса (напр. Person). Эту ошибку сложно обнаружить из-за static binding. Таким образом, если вы вызовете этот метод для an object своего класса, то метод не просто скомпorруется, а даже сделает это корректно. Однако, если вы положите ваш an object в коллекцию, например ArrayList и вызовете метод contains(), работа которого основана на методе equals(), то метод contains не сможет обнаружить ваш an object.

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

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

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

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

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

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

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

  4. Stringet des classes wrapper telles que Integer, Floatet Doubleremplacent la méthode equals(), mais StringBufferne remplacent pas.

  5. Dans la mesure du possible, créez des champs immutableà l'aide finalde variables en Java.

  6. Lorsque vous comparez Stringdes objets, utilisez equals()plutôt l'opérateur ==.

  7. Deux objets logiquement égaux mais chargés à partir d'objets différents ClassLoaderne peuvent pas être égaux. N'oubliez pas que la vérification avec getClass()sera renvoyée falsesi la classe du chargeur est différente.

  8. Utilisez @Overrideégalement l'annotation sur la méthode . hashCode, car cela évite des erreurs subtiles telles que la valeur de retour de int. Cependant, certains programmeurs renvoient long.

PS Chers collègues ! J'ai trouvé cet article utile pour résoudre des problèmes de niveau 21 ! Je vous souhaite bonne chance dans l'analyse de ce sujet, utilisez la traduction ! J'espère que vous m'aiderez à augmenter ma note, puisque maintenant je ne peux même plus laisser de commentaire sur ce forum. Merci beaucoup à tous ! Article original J'ai omis certains points faute de temps libre, mais j'ai traduit tout ce qu'il faut savoir pour résoudre les problèmes de niveau 21.
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION