JavaRush /Java Blog /Random-IT /Sovraccarico dei metodi equals() e hashCode() in Java
Coder
Livello 17

Sovraccarico dei metodi equals() e hashCode() in Java

Pubblicato nel gruppo Random-IT

Sostituzione dei metodi equals() e hashCode() in Java

Equalse hashCodesono i metodi fondamentali dichiarati nella classe Objecte contenuti nelle librerie Java standard. Sovraccarico dei metodi equals() e hashCode() in Java - 1Il metodo еquals()viene utilizzato per confrontare oggetti e hashCodegenerare un codice intero per l'oggetto. Questi metodi sono ampiamente utilizzati nelle librerie standard Java durante l'inserimento e il recupero di oggetti in file HashMap. Il metodo equalviene utilizzato anche per garantire che solo oggetti univoci vengano archiviati in HashSetaltre Setimplementazioni, nonché in tutti gli altri casi in cui è necessario confrontare gli oggetti. L'implementazione predefinita del metodo equals()nella classe java.lang.Objectconfronta i riferimenti agli indirizzi di memoria che le variabili memorizzano e restituisce truesolo se gli indirizzi corrispondono, in altre parole, le variabili si riferiscono allo stesso oggetto. Java consiglia di sovrascrivere i metodi equals()e hashCode()se si prevede che il confronto segua la logica naturale o la logica aziendale. Molte classi nelle librerie Java standard le sovrascrivono, ad esempio la classe Stringsovrascrive equalsin modo che restituisca truese il contenuto dei due oggetti confrontati è lo stesso. La classe wrapper sovrascrive Integeril metodo equalper eseguire un confronto numerico e così via. Poiché Java si basa HashMapanche sui metodi e per confrontare i rispettivi e , Java offre le seguenti regole per sovrascrivere questi metodi: HashTableequals()hashCode()keyvalues
  1. Riflessività: l'oggetto deve essere uguale a se stesso.
  2. Simmetrico: se a.equals(b)ritorna true, allora b.equals(a)deve tornare anche true.
  3. Transitività: se a.equals(b)ritorna truee b.equals(c)ritorna anche true, allora c.equals(a)deve ritornare anche true.
  4. Coerenza: le chiamate ripetute a un metodo equals()devono restituire lo stesso valore purché alcuni valori delle proprietà dell'oggetto non vengano modificati. Cioè, se due oggetti sono uguali in Java, allora saranno uguali finché le loro proprietà rimarranno invariate.
  5. Confronto null: L'oggetto deve essere controllato null. Se l'oggetto è uguale a null, il metodo dovrebbe restituire false, non NullPointerException. Ad esempio, a.equals(null)dovrebbe restituire false.

Accordo tra equals e hashCode in Java

  1. Se gli oggetti sono uguali nei risultati dell'esecuzione del metodo equals, allora hashcodedevono essere gli stessi.
  2. Se gli oggetti non sono uguali nei risultati dell'esecuzione del metodo equals, hashcodepossono essere uguali o diversi. Tuttavia, per migliorare le prestazioni, è preferibile che oggetti diversi restituiscano codici diversi.

Come sovrascrivere il metodo equals in 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. Stringe classi wrapper come Integer, Floate Doublesovrascrivono il metodo equals(), ma StringBuffernon sovrascrivono.

  5. Quando possibile, crea campi immutableutilizzando finalvariabili in Java.

  6. Quando confronti Stringgli oggetti, utilizza equals()invece l'operatore ==.

  7. Due oggetti logicamente uguali ma caricati da oggetti diversi ClassLoadernon possono essere uguali. Ricorda che il controllo con getClass()restituirà falsese la classe del caricatore è diversa.

  8. Utilizzare @Overridel'annotazione anche sul metodo . hashCode, in quanto ciò impedisce errori sottili come il valore restituito del metodo int.Tuttavia, alcuni programmatori restituiscono long.

PS Cari colleghi! Ho trovato questo articolo utile per risolvere i problemi del livello 21! Ti auguro buona fortuna nell'analizzare questo argomento, usa la traduzione! Spero che mi aiuterete ad aumentare la mia valutazione, dato che ora non posso nemmeno lasciare un commento su questo forum. Grazie mille a tutti! Articolo originale Ho omesso alcuni punti per mancanza di tempo libero, ma ho tradotto tutto quello che devi sapere per risolvere i problemi del livello 21.
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION