Membandingkan objek Java dengan equals () dan hashcode ()

Dalam Java Challenger ini Anda akan belajar bagaimana equals()dan hashcode()menggabungkannya untuk membuat perbandingan objek menjadi efisien dan mudah dalam program Java Anda. Sederhananya, metode ini bekerja sama untuk memverifikasi apakah dua objek memiliki nilai yang sama.  

Tanpa equals()dan hashcode()kita harus membuat ifperbandingan " " yang sangat besar , membandingkan setiap bidang dari sebuah objek. Ini akan membuat kode sangat membingungkan dan sulit dibaca. Bersama-sama, kedua metode ini membantu kami membuat kode yang lebih fleksibel dan kohesif.

Dapatkan kode sumber Java Challengers.

Mengganti sama dengan () dan hashcode () di Java

Metode overriding adalah teknik di mana perilaku kelas atau antarmuka induk ditulis kembali (diganti) dalam subkelas untuk memanfaatkan Polimorfisme. Setiap Objectdi Java menyertakan equals()dan hashcode()metode, tetapi harus diganti agar berfungsi dengan benar.

Untuk memahami cara kerja penggantian equals()dan   hashcode(), kita dapat mempelajari penerapannya di kelas inti Java. Di bawah ini adalah equals()metode di Objectkelas. Metode ini memeriksa apakah instance saat ini sama dengan yang diteruskan sebelumnya Object.

 public boolean equals(Object obj) { return (this == obj); } 

Jika hashcode()metode tidak diganti, metode default di Objectkelas akan dipanggil. Ini adalah metode asli , yang artinya akan dijalankan dalam bahasa lain seperti C, dan akan mengembalikan beberapa kode terkait alamat memori objek. (Tidaklah penting untuk mengetahui dengan tepat bagaimana metode ini bekerja kecuali Anda menulis kode JDK.)

 @HotSpotIntrinsicCandidate public native int hashCode(); 

Jika metode equals()dan hashcode()tidak diganti, Anda akan melihat metode di atas dipanggil. Dalam hal ini, metode tidak memenuhi tujuan sebenarnya dari equals()dan hashcode(), yaitu untuk memeriksa apakah dua atau lebih objek memiliki nilai yang sama.

Sebagai aturan, saat Anda mengganti, equals()Anda juga harus mengganti hashcode().

Membandingkan objek dengan persamaan ()

Kami menggunakan equals()metode untuk membandingkan objek di Java. Untuk menentukan apakah dua objek sama, equals()bandingkan nilai atribut objek:

 public class EqualsAndHashCodeExample { public static void main(String... equalsExplanation) { System.out.println(new Simpson("Homer", 35, 120) .equals(new Simpson("Homer",35,120))); System.out.println(new Simpson("Bart", 10, 120) .equals(new Simpson("El Barto", 10, 45))); System.out.println(new Simpson("Lisa", 54, 60) .equals(new Object())); } static class Simpson { private String name; private int age; private int weight; public Simpson(String name, int age, int weight) { this.name = name; this.age = age; this.weight = weight; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } Simpson simpson = (Simpson) o; return age == simpson.age && weight == simpson.weight && name.equals(simpson.name); } } } 

Pada perbandingan pertama, equals()bandingkan instance objek saat ini dengan objek yang telah dilewati. Jika kedua objek memiliki nilai yang sama, equals()akan dikembalikan true.

Dalam perbandingan kedua, equals()periksa untuk melihat apakah objek yang diteruskan adalah null , atau jika diketik sebagai kelas yang berbeda. Jika kelas yang berbeda maka objeknya tidak sama.

Terakhir, equals()bandingkan bidang objek. Jika dua objek memiliki nilai bidang yang sama, maka objek tersebut sama.

Menganalisis perbandingan objek

Sekarang, mari kita lihat hasil perbandingan ini dalam main()metode kita . Pertama, kami membandingkan dua Simpsonobjek:

 System.out.println(new Simpson("Homer", 35, 120).equals(new Simpson("Homer", 35, 120))); 

Objek di sini identik, jadi hasilnya akan sama true.

Selanjutnya, kami membandingkan dua Simpsonobjek lagi:

 System.out.println(new Simpson("Bart", 10, 45).equals(new Simpson("El Barto", 10, 45))); 

Objek-objek di sini hampir identik tetapi namanya berbeda: Bart dan El Barto. Oleh karena itu hasilnya akan seperti itu false.

Akhirnya, mari kita bandingkan Simpsonobjek dan instance dari kelas Object:

 System.out.println(new Simpson("Lisa", 54, 60).equals(new Object())); 

Dalam hal ini hasilnya adalah falsekarena tipe kelasnya berbeda.

sama dengan () versus ==

Sekilas, ==operator dan equals()metode mungkin tampak melakukan hal yang sama, tetapi sebenarnya cara kerjanya berbeda. The ==Operator membandingkan apakah dua referensi objek menunjuk ke objek yang sama. Sebagai contoh:

 System.out.println(homer == homer2); 

Dalam perbandingan pertama, kami memberi contoh dua Simpsoncontoh berbeda menggunakan newoperator. Karena itu, variabel homerdan homer2akan menunjuk ke Objectreferensi yang berbeda di heap memori. Jadi kita akan mendapatkan falsehasilnya.

System.out.println(homer.equals(homer2)); 

Dalam perbandingan kedua, kami mengganti equals()metode. Dalam hal ini hanya nama yang akan dibandingkan. Karena nama kedua Simpsonobjek tersebut adalah “Homer” maka hasilnya akan seperti itu true.

Mengidentifikasi objek secara unik dengan hashcode ()

Kami menggunakan hashcode()metode untuk mengoptimalkan kinerja saat membandingkan objek. Eksekusi   hashcode()mengembalikan ID unik untuk setiap objek dalam program Anda, yang membuat tugas membandingkan seluruh status objek menjadi lebih mudah.

Jika kode hash suatu objek tidak sama dengan kode hash objek lain, tidak ada alasan untuk mengeksekusi equals()metode ini: Anda hanya tahu bahwa kedua objek itu tidak sama. Di sisi lain, jika kode hash adalah sama, maka Anda harus menjalankan equals()metode untuk menentukan apakah nilai-nilai dan bidang yang sama.

Berikut contoh praktis dengan hashcode().

 public class HashcodeConcept { public static void main(String... hashcodeExample) { Simpson homer = new Simpson(1, "Homer"); Simpson bart = new Simpson(2, "Homer"); boolean isHashcodeEquals = homer.hashCode() == bart.hashCode(); if (isHashcodeEquals) { System.out.println("Should compare with equals method too."); } else { System.out.println("Should not compare with equals method because " + "the id is different, that means the objects are not equals for sure."); } } static class Simpson { int id; String name; public Simpson(int id, String name) { this.id = id; this.name = name; } @Override public boolean equals(Object o)  if (this == o) return true; if (o == null  @Override public int hashCode() { return id; } } } 

A hashcode()yang selalu mengembalikan nilai yang sama valid tetapi tidak terlalu efektif. Dalam hal ini perbandingan akan selalu kembali true, sehingga equals()metode tersebut akan selalu dijalankan. Tidak ada peningkatan kinerja dalam kasus ini.  

Menggunakan equals () dan hashcode () dengan koleksi

The Setantarmuka bertanggung jawab untuk memastikan tidak ada duplikat elemen akan dimasukkan dalam Setsubclass. Berikut ini adalah beberapa kelas yang mengimplementasikan Setantarmuka:

  • HashSet
  • TreeSet
  • LinkedHashSet
  • CopyOnWriteArraySet

Hanya elemen unik yang dapat dimasukkan ke dalam a Set, jadi jika Anda ingin menambahkan elemen ke HashSetkelas (misalnya), Anda harus terlebih dahulu menggunakan metode equals()dan hashcode()untuk memverifikasi bahwa elemen tersebut unik. Jika metode equals()dan hashcode()tidak diganti dalam kasus ini, Anda berisiko memasukkan elemen duplikat dalam kode.

Pada kode di bawah ini, kami menggunakan addmetode untuk menambahkan elemen baru ke HashSetobjek. Sebelum elemen baru ditambahkan, HashSetperiksa untuk melihat apakah elemen tersebut sudah ada dalam koleksi yang diberikan:

 if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) break; p = e; 

Jika objeknya sama, elemen baru tidak akan disisipkan.

Koleksi hash

Setbukan satu-satunya koleksi yang menggunakan equals()dan hashcode(). HashMap, Hashtable, dan LinkedHashMap juga memerlukan metode ini. Sebagai aturan, jika Anda melihat koleksi yang memiliki awalan "Hash," Anda dapat yakin bahwa itu memerlukan penggantian hashcode()dan equals()metode untuk membuat fitur mereka berfungsi dengan baik.  

Panduan untuk menggunakan equals () dan hashcode ()

Anda sebaiknya hanya menjalankan equals()metode untuk objek yang memiliki ID kode hash unik yang sama. Anda tidak boleh mengeksekusi equals()jika ID kode hash berbeda.

Tabel 1. Perbandingan kode hash

Jika hashcode()dibandingkan ... Kemudian …
mengembalikan true menjalankan equals()
mengembalikan salah jangan dieksekusi equals()

This principle is mainly used in Set or Hash collections for performance reasons.

Rules for object comparison

When a hashcode() comparison returns false, the equals() method must also return false. If the hashcode is different, then the objects are definitely not equal.

Table 2. Object comparison with hashcode()

When the hashcode comparison returns ... The equals() method should return ...
true true or false
false false

When the equals() method returns true, it means that the objects are equal in all values and attributes. In this case,  the hashcode comparison must be true as well.

Table 3. Object comparison with equals()

When the equals() method returns ... The hashcode() method should return ...
true true
false true or false

Take the equals() and hashcode() challenge!

It’s time to test your skills with the equals() and hashcode() methods.  Your goal in this challenge is to figure out the output of the two equals() method comparisons and guess the size of the Set collection.

To start, study the following code carefully:

 public class EqualsHashCodeChallenge { public static void main(String... doYourBest) { System.out.println(new Simpson("Bart").equals(new Simpson("Bart"))); Simpson overriddenHomer = new Simpson("Homer") { public int hashCode() { return (43 + 777) + 1; } }; System.out.println(new Simpson("Homer").equals(overriddenHomer)); Set set = new HashSet(Set.of(new Simpson("Homer"), new Simpson("Marge"))); set.add(new Simpson("Homer")); set.add(overriddenHomer); System.out.println(set.size()); } static class Simpson { String name; Simpson(String name) { this.name = name; } @Override public boolean equals(Object obj) { Simpson otherSimpson = (Simpson) obj; return this.name.equals(otherSimpson.name) && this.hashCode() == otherSimpson.hashCode(); } @Override public int hashCode() { return (43 + 777); } } } 

Remember, analyze the code first, guess the result, and then run the code. Your goal is to improve your skill with code analysis and absorb core Java concepts to make your code more powerful. Choose your answer before checking the correct answer below.

 A) true true 4 B) true false 3 C) true false 2 D) false true 3 

What just happened? Understanding equals() and hashcode()

In the first equals() method comparison, the result is true because the state of the object is exactly the same and the hashcode() method returns the same value for both objects.

In the second equals() method comparison, the hashcode() method is being overridden for the overridenHomer variable. The name is “Homer” for both Simpson objects, but the hashcode() method returns a different value for overriddenHomer. In this case, the final result from the the equals() method will be false because the method contains a comparison with the hashcode.

You might notice that the size of the collection is set to hold three Simpson objects. Let’s check this in a detailed way.

The first object in the set will be will be inserted normally:

 new Simpson("Homer"); 

The next object will be inserted normally, as well, because it holds a different value from the previous object:

 new Simpson("Marge"); 

Finally,  the following Simpson object has the same value as the first object. In this case the object won’t be inserted:

 set.add(new Simpson("Homer")); 

Seperti yang kita ketahui, overridenHomerobjek tersebut menggunakan nilai kode hash yang berbeda dari Simpson(“Homer”)instansiasi normal . Karenanya, elemen ini akan dimasukkan ke dalam koleksi:

 overriddenHomer; 

Kunci jawaban

Jawaban untuk penantang Java ini B . Outputnya adalah:

 true false 3 

Tantangan video! Debugging sama dengan () dan hashcode ()

Debugging adalah salah satu cara termudah untuk menyerap sepenuhnya konsep pemrograman sekaligus meningkatkan kode Anda. Dalam video ini Anda dapat mengikuti sementara saya men-debug dan menjelaskan Java equals()dan hashcode()tantangan.