Comparing Java objects with equals() and hashcode()

What is the contract betwixt equals() and hashcode()? Larn how these methods work together when comparing Java objects

woman equality abstract diversity
Thinkstock

In this Coffee Challenger y'all'll larn how equals() and hashcode() combine to make object comparisons efficient and easy in your Java programs. Only put, these methods work together to verify if two objects take the same values.

Without equals() and hashcode() we would have to create very large "if" comparisons, comparison every field from an object. This would make lawmaking really disruptive and hard to read. Together, these ii methods help united states create more flexible and cohesive code.

Overriding equals() and hashcode() in Java

Method overriding is a technique where the beliefs of the parent class or interface is written again (overridden) in the subclass in social club to take advantage of Polymorphism. Every Object in Java includes an equals() and a hashcode() method, but they must be overridden to piece of work properly.

To empathize how overriding works with equals() andhashcode(), we can report their implementation in the cadre Coffee classes. Beneath is the equals() method in the Object class. The method is checking whether the current example is the aforementioned as the previously passed Object.

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

When the hashcode() method is not overridden, the default method in the Object grade will be invoked. This is a native method, which means information technology volition be executed in another language similar C, and will return some code regarding the object's retention address. (It's not that important to know exactly how this method works unless you lot are writing JDK code.)

                              @HotSpotIntrinsicCandidate public native int hashCode();                          

When the equals() and hashcode() methods are non overridden, you volition see the above methods invoked instead. In this case, the methods are not fulfilling the existent purpose of equals() and hashcode(), which is to check whether two or more objects have the same values.

Every bit a dominion, when yous override equals() yous must also override hashcode().

Comparing objects with equals()

We use the equals() method to compare objects in Java. In order to decide if two objects are the same, equals() compares the values of the objects' attributes:

                              public class EqualsAndHashCodeExample {      public static void primary(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 form Simpson {          private String name;         private int age;         private int weight;          public Simpson(String name, int age, int weight) {             this.name = name;             this.age = historic period;             this.weight = weight;         }          @Override         public boolean equals(Object o) {             if (this == o) {                 return true;             }             if (o == aught || getClass() != o.getClass()) {                 render simulated;             }             Simpson simpson = (Simpson) o;             return historic period == simpson.age &&                     weight == simpson.weight &&                     name.equals(simpson.name);         }     }  }                          

In the commencement comparison, equals() compares the current object instance with the object that has been passed. If the two objects have the aforementioned values, equals() will return true.

In the second comparing, equals()checks to see whether the passed object is null, or if it's typed every bit a dissimilar class. If it's a different class so the objects are not equal.

Finally, equals() compares the objects' fields.  If two objects take the same field values, then the objects are the same.

Analyzing object comparisons

Now, allow's view the results of these comparisons in our primary() method. First, we compare 2 Simpson objects:

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

The objects hither are identical, and then the effect will be true.

Next, we compare ii Simpson objects again:

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

The objects here are nearly identical merely their names are different: Bart and El Barto. Therefore the result will exist fake.

Finally, let's compare a Simpson object and an instance of the class Object:

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

In this case the result will be false because the class types are different.

equals() versus ==

At first glance, the == operator and equals() method may appear to do the aforementioned thing, merely in truth they work differently. The == operator compares whether two object references betoken to the aforementioned object. For example:

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

In the first comparison, we instantiated two different Simpson instances using the new operator. Because of this, the variables homer and homer2 will point to different Object references in the memory heap. And so we'll accept faux every bit the result.

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

In the second comparison, we override the equals() method. In this example only the names will exist compared. Because the name of both Simpson objects is "Homer" the result volition exist true.

Uniquely identifying objects with hashcode()

We use the hashcode() method to optimize performance when comparing objects. Executinghashcode() returns a unique ID for each object in your plan, which makes the chore of comparing the whole country of the object much easier.

If an object's hashcode is non the same as another object's hashcode, at that place is no reason to execute the equals() method: yous just know the ii objects are not the same. On the other hand, if the hashcode is the aforementioned, and then you must execute the equals() method to determine whether the values and fields are the aforementioned.

Here's a practical example with hashcode().

                              public class HashcodeConcept {      public static void main(String... hashcodeExample) {         Simpson homer = new Simpson(i, "Homer");         Simpson bart = new Simpson(2, "Homer");          boolean isHashcodeEquals = homer.hashCode() == bart.hashCode();          if (isHashcodeEquals) {             System.out.println("Should compare with equals method likewise.");         } else {             System.out.println("Should not compare with equals method considering " +                     "the id is different, that ways the objects are non equals for sure.");         }     }       static class Simpson {         int id;         String name;          public Simpson(int id, Cord proper name) {             this.id = id;             this.proper name = proper noun;         }          @Override         public boolean equals(Object o) {             if (this == o) render truthful;             if (o == null || getClass() != o.getClass()) return false;             Simpson simpson = (Simpson) o;             return id == simpson.id &&                     proper name.equals(simpson.proper noun);         }          @Override         public int hashCode() {             return id;         }     } }                          

A hashcode() that ever returns the same value is valid but not very effective. In this case the comparison will e'er return true, and so the equals() method will always be executed. There is no functioning improvement in this case.

Using equals() and hashcode() with collections

The Gear up 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 up interface:

  • HashSet
  • TreeSet
  • LinkedHashSet
  • CopyOnWriteArraySet

Merely unique elements may be inserted into a Prepare, and then if you lot want to add an element to the HashSet course (for example), you lot 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 take chances inserting duplicate elements in the code.

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

                              if (e.hash == hash && ((k = e.key) == fundamental || (central != goose egg && key.equals(k))))        break;        p = e;                          

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

Guidelines for using equals() and hashcode()

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

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

Rules for object comparing

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

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 truthful besides.

Have the equals() and hashcode() claiming!

Information technology's time to examination your skills with the equals() and hashcode() methods.  Your goal in this challenge is to effigy out the output of the 2 equals() method comparisons and guess the size of the Set up collection.

To start, report the post-obit code carefully:

                              public form 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() {                 render (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);          Organisation.out.println(gear up.size());     }      static course Simpson {         Cord proper name;          Simpson(Cord name) {             this.name = proper 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() {             render (43 + 777);         }     }  }                          

Call back, analyze the code first, guess the outcome, and so run the code. Your goal is to improve your skill with code analysis and absorb core Java concepts to brand your lawmaking more than powerful. Choose your answer earlier checking the right answer below.

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

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

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

In the second equals() method comparison, the hashcode() method is beingness overridden for the overridenHomer variable. The proper noun is "Homer" for both Simpson objects, but the hashcode() method returns a unlike 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. Permit's check this in a detailed style.

The starting time object in the gear up volition be will be inserted normally:

                              new Simpson("Homer");                          

The adjacent object will be inserted normally, every bit well, because it holds a unlike value from the previous object:

                              new Simpson("Marge");                          

Finally,  the post-obit Simpson object has the same value as the beginning object. In this instance the object won't be inserted:

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

As we know, the overridenHomer object uses a different hashcode value from the normal Simpson("Homer") instantiation. For this reason, this element will exist inserted into the collection:

                              overriddenHomer;                          

Video claiming! Debugging equals() and hashcode()

Debugging is one of the easiest means to fully absorb programming concepts while likewise improving your code. In this video you tin can follow along while I debug and explain the Coffee equals() and hashcode() challenge.