JavaRush /Java Blog /Random-ID /Membebani metode sama dengan() dan hashCode() di Java
Coder
Level 17

Membebani metode sama dengan() dan hashCode() di Java

Dipublikasikan di grup Random-ID

Mengganti metode sama dengan() dan kode hash() di Java

Equalsdan hashCodemerupakan metode dasar yang dideklarasikan di kelas Objectdan terdapat dalam perpustakaan Java standar. Membebani metode sama dengan() dan hashCode() di Java - 1Metode ini еquals()digunakan untuk membandingkan objek dan hashCodemenghasilkan kode integer untuk objek tersebut. Metode ini banyak digunakan di perpustakaan standar Java saat menyisipkan dan mengambil objek dalam format HashMap. Metode ini equaljuga digunakan untuk memastikan bahwa hanya objek unik yang disimpan dalam implementasi HashSetlain Set, serta dalam kasus lain di mana objek perlu dibandingkan. Implementasi default metode equals()di kelas java.lang.Objectmembandingkan referensi ke alamat memori yang disimpan dan dikembalikan oleh variabel truehanya jika alamatnya cocok, dengan kata lain, variabel merujuk ke objek yang sama. Java merekomendasikan untuk mengganti metode equals()and hashCode()jika Anda mengharapkan perbandingan dilakukan berdasarkan logika natural atau logika bisnis. Banyak kelas di perpustakaan Java standar yang menimpanya, misalnya kelas tersebut Stringmenimpa equalssehingga kembali truejika isi kedua objek yang dibandingkan sama. Kelas wrapper mengambil alih Integermetode equaluntuk melakukan perbandingan numerik, dan seterusnya. Karena Java HashMapjuga mengandalkan metode dan untuk membandingkan dan , Java menawarkan aturan berikut untuk mengganti metode ini: HashTableequals()hashCode()keyvalues
  1. Refleksivitas: Objek harus sama dengan dirinya sendiri.
  2. Simetris: jika a.equals(b)kembali true, maka b.equals(a)harus kembali juga true.
  3. Transitivitas: jika a.equals(b)ia kembali truedan b.equals(c)juga kembali true, maka c.equals(a)ia juga harus kembali true.
  4. Konsistensi: Panggilan berulang ke suatu metode equals()harus mengembalikan nilai yang sama selama beberapa nilai properti objek tidak berubah. Artinya, jika dua objek sama di Java, maka keduanya akan sama selama propertinya tidak berubah.
  5. Perbandingan null: Objek harus diperiksa null. Jika objeknya sama dengan null, maka metode tersebut harus mengembalikan false, bukan NullPointerException. Misalnya, a.equals(null)ia harus mengembalikan false.

Perjanjian antara sama dengan dan kode hash di Java

  1. Jika objek-objeknya sama dalam hasil eksekusi metode equals, maka objek-objek tersebut hashcodeharus sama.
  2. Jika objek-objek tersebut tidak sama dalam hasil eksekusi metode equals, maka objek-objek tersebut hashcodedapat sama atau berbeda. Namun, untuk meningkatkan kinerja, lebih baik objek yang berbeda mengembalikan kode yang berbeda.

Cara mengganti metode yang sama di 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. Stringdan kelas pembungkus seperti Integer, Floatdan Doublemengganti metode equals(), tetapi StringBuffertidak menimpa.

  5. Jika memungkinkan, buat kolom immutablemenggunakan finalvariabel di Java.

  6. Saat membandingkan Stringobjek, gunakan equals()operator .sebagai gantinya ==.

  7. Dua objek yang secara logis sama tetapi diambil dari objek yang berbeda ClassLoadertidak bisa sama. Ingatlah bahwa pengecekan dengan getClass()akan kembali falsejika kelas pemuat berbeda.

  8. Gunakan @Overridejuga anotasi pada metode . hashCode, karena ini mencegah kesalahan halus seperti nilai kembalian .Namun int, beberapa pemrogram mengembalikan long.

PS Rekan-rekan yang terhormat! Saya menemukan artikel ini berguna dalam memecahkan masalah level 21! Saya harap Anda beruntung dalam menganalisis topik ini, gunakan terjemahannya! Saya harap Anda membantu saya menaikkan peringkat saya, karena sekarang saya bahkan tidak dapat memberikan komentar di forum ini. Terima kasih banyak semuanya! Artikel asli Saya menghilangkan beberapa poin karena kurangnya waktu luang, tetapi saya menerjemahkan semua yang perlu Anda ketahui untuk menyelesaikan masalah level 21.
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION