Membandingkan objek Java dengan sama () dan kod hash ()

Dalam Java Challenger ini, anda akan belajar bagaimana equals()dan hashcode()menggabungkan untuk membuat perbandingan objek yang efisien dan mudah dalam program Java anda. Ringkasnya, kaedah ini berfungsi bersama untuk mengesahkan sama ada dua objek mempunyai nilai yang sama.  

Tanpa equals()dan hashcode()kita mesti membuat ifperbandingan yang sangat besar , membandingkan setiap medan dari objek. Ini akan menjadikan kod benar-benar membingungkan dan sukar dibaca. Bersama-sama, kedua kaedah ini membantu kita membuat kod yang lebih fleksibel dan padat.

Dapatkan kod sumber Java Challengers.

Overriding sama dengan () dan hashcode () di Java

Kaedah overriding adalah teknik di mana tingkah laku kelas induk atau antara muka ditulis semula (diganti) di subkelas untuk memanfaatkan Polimorfisme. Setiap Objectdi Java termasuk equals()dan dan hashcode()metode, tetapi mereka harus diganti untuk berfungsi dengan baik.

Untuk memahami bagaimana penggantian berfungsi dengan equals()dan   hashcode(), kita dapat mempelajari pelaksanaannya di kelas inti Java. Berikut adalah equals()kaedah di Objectkelas. Kaedahnya adalah memeriksa sama ada contoh semasa sama dengan yang dilalui sebelumnya Object.

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

Apabila hashcode()kaedah tidak diganti, kaedah lalai di Objectkelas akan dipanggil. Ini adalah kaedah asli , yang bermaksud ia akan dijalankan dalam bahasa lain seperti C, dan akan mengembalikan beberapa kod mengenai alamat memori objek. (Tidak penting untuk mengetahui dengan tepat bagaimana kaedah ini berfungsi melainkan anda menulis kod JDK.)

 @HotSpotIntrinsicCandidate public native int hashCode(); 

Apabila kaedah equals()dan hashcode()kaedah tidak diganti, anda akan melihat kaedah di atas dipanggil sebagai gantinya. Dalam kes ini, kaedah tidak memenuhi tujuan sebenar equals()dan hashcode(), iaitu untuk memeriksa sama ada dua atau lebih objek mempunyai nilai yang sama.

Sebagai peraturan, apabila anda menimpa, equals()anda juga mesti menimpa hashcode().

Membandingkan objek dengan sama ()

Kami menggunakan equals()kaedah untuk membandingkan objek di Jawa. Untuk menentukan sama ada dua objek sama, equals()membandingkan 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()membandingkan contoh objek semasa dengan objek yang telah dilalui. Sekiranya kedua-dua objek tersebut mempunyai nilai yang sama, equals()akan kembali true.

Dalam perbandingan kedua, equals()periksa untuk melihat sama ada objek yang dilalui adalah nol , atau jika ia ditaip sebagai kelas yang berbeza. Sekiranya ia adalah kelas yang berbeza maka objek tidak sama.

Akhirnya, equals()membandingkan medan objek. Sekiranya dua objek mempunyai nilai medan yang sama, maka objeknya sama.

Menganalisis perbandingan objek

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

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

Objek di sini sama, jadi hasilnya akan menjadi sama true.

Seterusnya, kita membandingkan dua Simpsonobjek sekali lagi:

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

Objek di sini hampir sama tetapi namanya berbeza: Bart dan El Barto. Oleh itu hasilnya akan false.

Akhirnya, mari kita bandingkan Simpsonobjek dan contoh objek Objek:

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

Dalam kes ini, hasilnya adalah falsekerana jenis kelasnya berbeza.

sama dengan () berbanding ==

Pada pandangan pertama, ==pengendali dan equals()kaedah mungkin melakukan perkara yang sama, tetapi sebenarnya mereka bekerja dengan cara yang berbeza. The ==operator membandingkan sama ada dua rujukan objek menunjukkan objek yang sama. Sebagai contoh:

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

Dalam perbandingan pertama, kami menunjukkan dua Simpsoncontoh yang berbeza menggunakan newoperator. Oleh kerana itu, pemboleh ubah homerdan homer2akan menunjukkan Objectrujukan yang berbeza di timbunan memori. Oleh itu, kita akan mendapat falsehasilnya.

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

Dalam perbandingan kedua, kami mengatasi equals()kaedah. Dalam kes ini hanya nama yang akan dibandingkan. Kerana nama kedua Simpsonobjek tersebut adalah "Homer" hasilnya akan menjadi true.

Mengenal pasti objek dengan kod hash ()

Kami menggunakan hashcode()kaedah untuk mengoptimumkan prestasi ketika membandingkan objek. Pelaksanaan   hashcode()mengembalikan ID unik untuk setiap objek dalam program anda, yang menjadikan tugas membandingkan keseluruhan keadaan objek menjadi lebih mudah.

If an object’s hashcode is not the same as another object’s hashcode, there is no reason to execute the equals() method: you just know the two objects are not the same. On the other hand, if the hashcode is the same, then you must execute the equals() method to determine whether the values and fields are the same.

Here’s a practical example with 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() that always returns the same value is valid but not very effective. In this case the comparison will always return true, so the equals() method will always be executed. There is no performance improvement in this case.  

Using equals() and hashcode() with collections

The Set interface is responsible for ensuring no duplicate elements will be inserted in a Set subclass. The following are some of the classes that implement the Set interface:

  • HashSet
  • TreeSet
  • LinkedHashSet
  • CopyOnWriteArraySet

Only unique elements may be inserted into a Set, so if you want to add an element to the HashSet class (for example), you must first use the equals() and hashcode() methods to verify that the element is unique. If the equals() and hashcode()methods weren’t overridden in this case, you would risk inserting duplicate elements in the code.

In the code below, we’re using the add method to add a new element  to a HashSet object. Before the new element is added, HashSet checks to see whether the element  already exists in the given collection:

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

If the object is the same, the new element won’t be inserted.

Hash collections

Set isn’t the only collection that makes use of equals() and hashcode(). HashMap, Hashtable, and LinkedHashMap also require these methods. As a rule, if you see a collection that has the prefix of “Hash,” you can be sure that it requires overriding the hashcode() and equals() methods to make their features work properly.  

Guidelines for using equals() and hashcode()

You should only execute an equals() method for objects that have the same unique hashcode ID. You should not execute equals() when the hashcode ID is different.

Table 1. Hashcode comparisons

If the hashcode() comparison ... Then …
returns true execute equals()
returns false do not execute 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 menggunakan nilai kod hash yang berbeza dari keadaan biasa Simpson(“Homer”). Atas sebab ini, elemen ini akan dimasukkan ke dalam koleksi:

 overriddenHomer; 

Kunci jawapan

Jawapan kepada pencabar Java ini adalah B . Hasilnya adalah:

 true false 3 

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

Penyahpepijatan adalah salah satu kaedah termudah untuk menyerap sepenuhnya konsep pengaturcaraan sambil meningkatkan kod anda. Dalam video ini anda boleh mengikuti sementara saya membuat debug dan menerangkan Java equals()dan hashcode()cabarannya.