JavaRush /Java Blog /Random-ID /Rehat kopi #168. Mengapa mengganti metode sama dengan dan...

Rehat kopi #168. Mengapa mengganti metode sama dengan dan kode hash di Java?

Dipublikasikan di grup Random-ID

Mengapa mengganti metode sama dengan dan kode hash di Java?

Sumber: Medium Artikel ini berfokus pada dua metode yang terkait erat: sama dengan() dan kode hash() . Anda akan mempelajari cara mereka berinteraksi satu sama lain dan cara menggantinya dengan benar. Rehat kopi #168.  Mengapa mengganti metode sama dengan dan kode hash di Java?  - 1

Mengapa kita mengganti metode sama dengan()?

Di Java, kita tidak bisa membebani perilaku operator seperti == , += , -+ . Mereka bekerja sesuai dengan proses tertentu. Misalnya, perhatikan pengoperasian operator == .

Bagaimana cara kerja operator ==?

Ia memeriksa apakah dua referensi yang dibandingkan menunjuk ke contoh yang sama di memori. Operator == hanya akan bernilai true jika kedua referensi mewakili instance yang sama di memori. Mari kita lihat contoh kodenya:
public class Person {
      private Integer age;
      private String name;

      ..getters, setters, constructors
      }
Katakanlah dalam program Anda, Anda telah membuat dua objek Person di tempat berbeda dan ingin membandingkannya.
Person person1 = new Person("Mike", 34);
Person person2 = new Person("Mike", 34);
System.out.println( person1 == person2 ); --> will print false!
Dari segi bisnis, keduanya terlihat sama bukan? Namun untuk JVM keduanya tidak sama. Karena keduanya dibuat menggunakan kata kunci new , instance ini ditempatkan di segmen memori yang berbeda. Oleh karena itu operator == akan mengembalikan false . Tetapi jika kita tidak dapat mengganti operator == , lalu bagaimana kita memberi tahu JVM bahwa kita ingin kedua objek ini diperlakukan sama? Di sinilah metode .equals() berperan . Anda dapat mengganti sama dengan() untuk memeriksa apakah beberapa objek memiliki nilai yang sama untuk bidang tertentu agar dianggap sama. Anda dapat memilih bidang mana yang akan dibandingkan. Jika kita mengatakan bahwa dua objek Person akan sama hanya jika mereka memiliki umur dan nama yang sama, maka IDE akan menghasilkan sesuatu seperti ini untuk secara otomatis membuat equal() :
@Override
public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age &&
                name.equals(person.name);
    }
Mari kita kembali ke contoh sebelumnya.
Person person1 = new Person("Mike", 34);
Person person2 = new Person("Mike", 34);
System.out.println ( person1 == person2 ); --> will print false!
System.out.println ( person1.equals(person2) ); --> will print true!
Ya, kita tidak bisa membebani operator == secara berlebihan untuk membandingkan objek sesuai keinginan kita, tetapi Java memberi kita cara lain - metode sama dengan() , yang dapat kita timpa sesuai keinginan. Ingatlah bahwa jika kita tidak menyediakan versi khusus .equals() (juga dikenal sebagai override) di kelas kita, maka .equals() yang telah ditentukan sebelumnya dari kelas Object dan operator == akan berperilaku sama. Metode equal() default , yang diwarisi dari Object , akan memeriksa apakah kedua instance yang dibandingkan sama di memori!

Mengapa kita mengganti metode hashCode()?

Beberapa struktur data di Java, seperti HashSet dan HashMap , menyimpan elemennya berdasarkan fungsi hash yang diterapkan pada elemen tersebut. Fungsi hashnya adalah hashCode() . Jika kita mempunyai pilihan untuk mengganti metode .equals() , maka kita juga harus mempunyai pilihan untuk mengganti metode hashCode() . Ada alasan untuk ini. Lagi pula, implementasi default hashCode() , yang diwarisi dari Object , menganggap semua objek di memori sebagai unik! Tapi mari kita kembali ke struktur data hash ini. Ada aturan untuk struktur data ini. HashSet tidak boleh berisi nilai duplikat dan HashMap tidak boleh berisi kunci duplikat. HashSet diimplementasikan menggunakan HashMap sedemikian rupa sehingga setiap nilai HashSet disimpan sebagai kunci di HashMap . Bagaimana cara kerja HashMap ? HashMap adalah array asli dengan banyak segmen. Setiap segmen memiliki daftar tertaut ( linkedList ). Daftar tertaut ini menyimpan kunci kami. HashMap menemukan linkedList yang benar untuk setiap kunci menggunakan metode hashCode() , lalu melakukan iterasi melalui semua elemen linkedList tersebut dan menerapkan metode sama dengan() ke setiap elemen tersebut untuk memeriksa apakah elemen tersebut ada di sana. Kunci duplikat tidak diperbolehkan. Rehat kopi #168.  Mengapa mengganti metode sama dengan dan kode hash di Java?  - 2Saat kita memasukkan sesuatu ke dalam HashMap , kuncinya disimpan di salah satu daftar tertaut ini. Daftar tertaut mana yang akan menyimpan kunci ini ditunjukkan oleh hasil metode hashCode() untuk kunci tersebut. Artinya, jika key1.hashCode() menghasilkan 4, maka key1 tersebut akan disimpan di segmen ke-4 array di LinkedList yang ada di sana . Secara default, metode hashCode() mengembalikan hasil yang berbeda untuk setiap instance. Jika kita memiliki equal() default yang berperilaku seperti == , memperlakukan semua instance di memori sebagai objek berbeda, maka tidak akan ada masalah. Seperti yang mungkin Anda ingat, dalam contoh sebelumnya kami mengatakan bahwa kami ingin instance Person dianggap sama jika usia dan namanya sama.
Person person1 = new Person("Mike", 34);
    Person person2 = new Person("Mike", 34);
    System.out.println ( person1.equals(person2) );  --> will print true!
Sekarang mari kita buat peta untuk menyimpan instance ini sebagai kunci dengan string tertentu sebagai pasangan nilai.
Map<Person, String> map = new HashMap();
map.put(person1, "1");
map.put(person2, "2");
Di kelas Person , kami belum mengganti metode kode hash , tetapi kami memiliki metode sama dengan yang diganti . Karena hashCode default memberikan hasil yang berbeda untuk instance Java person1.hashCode() dan person2.hashCode() yang berbeda , ada kemungkinan besar untuk mendapatkan hasil yang berbeda. Peta kita dapat diakhiri dengan orang berbeda dalam daftar tertaut berbeda. Rehat kopi #168.  Mengapa mengganti metode sama dengan dan kode hash di Java?  - 3Ini bertentangan dengan logika HashMap . Lagi pula, HashMap tidak boleh memiliki beberapa kunci yang identik! Intinya adalah hashCode() default yang diwarisi dari kelas Object tidaklah cukup. Bahkan setelah kita mengganti metode sama dengan() dari kelas Person . Itu sebabnya kita harus mengganti metode hashCode() setelah kita mengganti metode yang sama . Sekarang mari kita perbaiki ini. Kita perlu mengganti metode hashCode() agar memperhitungkan bidang yang sama dengan same() , yaitu age dan name .
public class Person {
      private Integer age;
      private String name;

      ..getters, setters, constructors
@Override
public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age &&
                name.equals(person.name);
    }
@Override
public int hashCode() {
        int prime = 31;
        return prime*Objects.hash(name, age);
    }
Dalam metode hashCode() kami menggunakan nilai sederhana (Anda dapat menggunakan nilai lainnya). Namun, disarankan untuk menggunakan bilangan prima untuk mengurangi masalah. Mari kita coba simpan lagi kunci-kunci ini di HashMap kita :
Map<Person, String> map = new HashMap();
map.put(person1, "1");
map.put(person2, "2");
person1.hashCode() dan person2.hashCode() akan sama. Katakanlah mereka 0. HashMap akan menuju ke segmen 0 dan di dalamnya LinkedList akan menyimpan person1 sebagai kunci dengan nilai “1”. Dalam kasus kedua, ketika HashMap pergi ke keranjang 0 lagi untuk menyimpan kunci person2 dengan nilai “2”, ia akan melihat bahwa kunci lain yang sama dengan itu sudah ada di sana. Dengan cara ini akan menimpa kunci sebelumnya. Dan hanya person2 kunci yang akan ada di HashMap kami . Inilah cara kami mempelajari cara kerja aturan HashMap , yang menyatakan bahwa Anda tidak dapat menggunakan beberapa kunci yang identik! Namun, perlu diingat bahwa instance yang tidak sama dapat memiliki kode hash yang sama, dan instance yang sama harus mengembalikan kode hash yang sama.Rehat kopi #168.  Mengapa mengganti metode sama dengan dan kode hash di Java?  - 4
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION