JavaRush /Blog Java /Random-MS /Bekerja dengan kaedah hashCode() dan equals() dalam Java
Lenchik854
Tahap
Chernihiv

Bekerja dengan kaedah hashCode() dan equals() dalam Java

Diterbitkan dalam kumpulan
Dalam catatan ini saya akan menggariskan pemahaman saya tentang kaedah hashCode()dan equals(). Saya ingin bercakap tentang pelaksanaan lalai mereka, serta cara mengatasinya dengan betul. Saya juga akan menulis tentang melaksanakan kaedah ini menggunakan kelas pembantu pakej Apache Common. Bekerja dengan kaedah hashCode() dan equals() dalam Java - 1Kandungan siaran ini:
  1. Menggunakan hashCode()dan equals().
  2. Gantikan tingkah laku lalai.
  3. Mengatasi hashCode()dan equals()menggunakan Apache Commons Lang.
  4. Sesuatu yang penting untuk diingati.
  5. Perhatian Khusus Apabila Menggunakan ORM.
Kaedah hashCode()dan equals()ditakrifkan dalam class Object, iaitu kelas induk untuk objek java. Oleh itu, semua objek java mewarisi pelaksanaan lalai daripada kaedah ini.

Menggunakan hashCode() dan equals()

Kaedah ini hashCode()digunakan untuk mendapatkan nombor integer unik untuk objek tertentu. Apabila objek perlu disimpan sebagai struktur data dalam jadual cincang (juga dipanggil baldi), nombor ini digunakan untuk menentukan lokasinya dalam jadual itu. Secara lalai, kaedah hashCode()untuk objek mengembalikan nombor lokasi memori tempat objek disimpan. Kaedah equals(), seperti namanya, digunakan untuk menyemak kesamaan dua objek sahaja. Pelaksanaan lalai kaedah ini hanya menyemak rujukan dua objek untuk melihat sama ada ia setara.

Mengatasi tingkah laku lalai

Semuanya berfungsi dengan baik selagi anda tidak mengatasi mana-mana kaedah ini dalam kelas anda. Tetapi kadangkala aplikasi perlu menukar tingkah laku lalai sesetengah objek. Mari kita ambil contoh di mana anda mempunyai Employee. Mari kita tulis struktur minimum yang mungkin bagi kelas sedemikian.
public class Employee
{
    private Integer id;
    private String firstname;
    private String lastName;
    private String department;

    public Integer getId() {
        return id;
    }
    public void setId(Integer 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;
    }
    public String getDepartment() {
        return department;
    }
    public void setDepartment(String department) {
        this.department = department;
    }
}
Kelas yang diterangkan di atas Employeemempunyai beberapa atribut asas dan kaedah pengakses. Sekarang mari kita lihat situasi mudah di mana kita perlu membandingkan dua objek kelas Employee.
public class EqualsTest {
    public static void main(String[] args) {
        Employee e1 = new Employee();
        Employee e2 = new Employee();

        e1.setId(100);
        e2.setId(100);
        //Печатает false в консоли
        System.out.println(e1.equals(e2));
    }
}
Ia tidak memerlukan peramal untuk meneka bahawa kaedah yang ditulis di atas akan mengembalikan "palsu". Tetapi adakah ini sebenarnya betul, memandangkan kedua-dua objek ini adalah sama? Dalam aplikasi masa nyata, kaedah mesti kembali benar. Untuk mencapai tingkah laku yang betul, kita perlu mengatasi kaedah equals(), seperti yang dilakukan di bawah:
public boolean equals(Object o) {
        if(o == null)
        {
            return false;
        }
        if (o == this)
        {
           return true;
        }
        if (getClass() != o.getClass())
        {
            return false;
        }
        Employee e = (Employee) o;
        return (this.getId() == e.getId());
}
Tambahkan kaedah ini pada kelas anda Employeedan semakan kesetaraan akan mengembalikan "benar". Namun, adakah kita telah melakukan segala-galanya? Belum lagi. Mari uji kelas kami yang diubah suai dengan satu cara lagi.
import java.util.HashSet;
import java.util.Set;

public class EqualsTest
{
    public static void main(String[] args)
    {
        Employee e1 = new Employee();
        Employee e2 = new Employee();

        e1.setId(100);
        e2.setId(100);

        //Печатает 'true'
        System.out.println(e1.equals(e2));

        Set employees = new HashSet();
        employees.add(e1);
        employees.add(e2);
        //Печатает два an object
        System.out.println(employees);
    }
}
Perintah System.out.println(employee)mencetak dua objek. Jika kedua-dua objek adalah setara, dan Sethanya objek unik yang terkandung di dalamnya, maka HashSetharus ada hanya satu contoh di dalamnya, i.e. kedua-dua objek merujuk kepada keadaan kelas yang sama Employee. Apa yang kita terlepas? Kami terlepas kaedah penting kedua hashCode(). Seperti yang dinyatakan dalam dokumentasi java, jika anda mengatasi kaedah equals(), maka anda dikehendaki mengatasi kaedah hashCode(). Jadi mari kita tambah kaedah lain pada kelas kita Employee.
@Override
 public int hashCode()
 {
    final int PRIME = 31;
    int result = 1;
    result = PRIME * result + getId();
    return result;
 }
Kami menambah kaedah ini sekali pada kelas kami, dan hanya satu objek akan dicetak, dan dengan itu, menyemak kesetaraan e1 dan e2 menunjukkan benar.

Mengatasi hashCode()dan equals()menggunakan Apache Commons Lang

Apache Commons menyediakan dua kelas pembantu yang hebat untuk kaedah panggilan hashCode()dan equals(). Di bawah kita lihat penggunaannya:
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
public class Employee
{
 private Integer id;
 private String firstname;
 private String lastName;
 private String department;
public Integer getId() {
    return id;
 }
 public void setId(Integer 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;
 }
 public String getDepartment() {
    return department;
 }
 public void setDepartment(String department) {
    this.department = department;
 }
@Override
 public int hashCode()
 {
    final int PRIME = 31;
    return new HashCodeBuilder(getId()%2==0?getId()+1:getId(), PRIME).
           toHashCode();
 }
@Override
 public boolean equals(Object o) {
    if (o == null)
       return false;
    if (o == this)
       return true;
    if (o.getClass() != getClass())
       return false;
    Employee e = (Employee) o;
       return new EqualsBuilder().
              append(getId(), e.getId()).
              isEquals();
    }
 }
Sebaliknya, jika anda menggunakan salah satu editor kod, mereka juga sepatutnya dapat memanggil beberapa struktur yang bagus untuk anda. Sebagai contoh, jika dalam Eclipse IDE anda klik kanan pada kelas >> sumber > Menjana Kod hash() dan sama() ... ia akan menjana pelaksanaan yang sangat bagus untuk anda. Bekerja dengan kaedah hashCode() dan equals() dalam Java - 2Sesuatu yang penting untuk diingati.
  1. Sentiasa gunakan atribut objek yang sama untuk memanggil kedua-dua dan hashCode()dan equals(). Hanya dalam kes kami, kami menggunakan employee id.
  2. Kaedah equals()mesti berterusan (jika objek tidak berubah, kaedah mesti mengembalikan nilai yang sama).
  3. Bila-bila masa a.equals(b), maka a.hashCode()mesti sama dengan b.hashCode().
  4. Jika anda mengatasi satu kaedah, anda mesti mengatasi kaedah kedua.

Perhatian Khusus Apabila Menggunakan ORM

Jika anda berurusan dengan ORM (ru.wikipedia.org/wiki/ORM), maka sentiasa gunakan getter dan jangan sekali-kali menggunakan rujukan medan hashCode(). equals()Ini kerana dalam ORM, dari semasa ke semasa medan dimuatkan menggunakan beban malas dan tidak boleh diakses sehingga pengambilnya dipanggil. Sebagai contoh, dalam kelas kami Employee, kami menggunakan e1.id == e2.id. Kemungkinan besar imedan d dimuatkan menggunakan pemuatan malas. Salah satu medan mungkin 0 atau batal dan kami akan mendapat tingkah laku yang salah. Tetapi, jika , digunakan e1.getId() == e2.getId(), kita boleh pastikan walaupun medan dimuatkan menggunakan pemuatan malas; memanggil pengambil akan mengisi medan terlebih dahulu. Itu sahaja yang saya tahu tentang hashCode()dan kaedah equals(). Harap ini membantu seseorang di suatu tempat. Semoga berjaya dalam pelajaran!! ps Ini adalah percubaan pertama saya untuk terjemahan. Saya cuba menyampaikan segalanya sedekat mungkin dengan apa yang ingin disampaikan oleh penulis. Jika anda mempunyai sebarang komen, sila tulis dalam komen. Jangan menilai secara ketat :-))) Artikel asal
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION