# 5) Equals and Hashcode

## ***1) equals()***

The *Object* class defines both the *equals()* and *hashCode()* methods – which means that these two methods are implicitly defined in every Java class, including the ones we create:

![](/files/-LaVw1SzGSSiB3WQq98K)

We would expect *income.equals(expenses)* to return *true*. But with the *Money* class in its current form, it won’t.

**The default implementation of&#x20;*****equals()*****&#x20;in the class&#x20;*****Object*****&#x20;says that equality is the same as object identity. And&#x20;*****income*****&#x20;and&#x20;*****expenses*****&#x20;are two distinct instances.**

### **Without Equals :**

```java
package com.gs.ilp.corejava.collectionsFramework2.equalsandhashcode;

public class WrongMoney {
	int amount;
	String currencyCode;

	public WrongMoney() {
		super();
		// TODO Auto-generated constructor stub
	}

	public WrongMoney(int amount, String currencyCode) {
		super();
		this.amount = amount;
		this.currencyCode = currencyCode;
	}

}
```

```java
package com.gs.ilp.corejava.collectionsFramework2.equalsandhashcode;

public class TestWrongMoney {
	public static void main(String[] args) {
		WrongMoney income = new WrongMoney(55, "USD");
		WrongMoney expenses = new WrongMoney(55, "USD");
		boolean balanced = income.equals(expenses);
		System.out.println("Are the equal :" + balanced);
	}

}
```

![](/files/-Lapm0Gg2fjDle5nVqcF)

### ***1.1)*****&#x20;Overriding&#x20;*****equals()***

Let’s override the *equals()* method so that it doesn’t consider only object identity, but rather also the value of the two relevant properties:

![](/files/-LaVwJ7x_emA5E-Czlrd)

### Genrating Equals/Hashcode using Eclipse:

#### Way 1:  Using getClass()

![](/files/-LaprbVDeCKhA_fZru7p)

![](/files/-LapreFxd8CQk04A6UAy)

```java
package com.gs.ilp.corejava.collectionsFramework2.equalsandhashcode;

public class Money {
	int amount;
	String currencyCode;

	public Money() {
		super();
		// TODO Auto-generated constructor stub
	}

	public Money(int amount, String currencyCode) {
		super();
		this.amount = amount;
		this.currencyCode = currencyCode;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Money other = (Money) obj;
		if (amount != other.amount)
			return false;
		if (currencyCode == null) {
			if (other.currencyCode != null)
				return false;
		} else if (!currencyCode.equals(other.currencyCode))
			return false;
		return true;
	}

}
```

#### Way 2: Using instanceOf()

![](/files/-LaprkVZyx7woLELMiH8)

### With Equals :

```java
package com.gs.ilp.corejava.collectionsFramework2.equalsandhashcode;

public class Money {
	int amount;
	String currencyCode;

	public Money() {
		super();
		// TODO Auto-generated constructor stub
	}

	public Money(int amount, String currencyCode) {
		super();
		this.amount = amount;
		this.currencyCode = currencyCode;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (!(obj instanceof Money))
			return false;
		Money other = (Money) obj;
		if (amount != other.amount)
			return false;
		if (currencyCode == null) {
			if (other.currencyCode != null)
				return false;
		} else if (!currencyCode.equals(other.currencyCode))
			return false;
		return true;
	}

	

}

```

```java
package com.gs.ilp.corejava.collectionsFramework2.equalsandhashcode;

public class TestMoney {
	public static void main(String[] args) {
		Money income = new Money(55, "USD");
		Money expenses = new Money(55, "USD");
		boolean balanced = income.equals(expenses);
		System.out.println("Are the equal :"+balanced);
	}
}
```

![](/files/-LapmQszcZwHBKkx-vUK)

### [***https://stackoverflow.com/questions/596462/any-reason-to-prefer-getclass-over-instanceof-when-generating-equals***](https://stackoverflow.com/questions/596462/any-reason-to-prefer-getclass-over-instanceof-when-generating-equals)

### **1.2)&#x20;*****equals()*****&#x20;Contract**

Java SE defines a contract that our implementation of the *equals()* method must fulfill. **Most of the criteria are common sense.** The *equals()* method must be:

* *reflexive*: an object must equal itself
* *symmetric*: ***x.equals(y)*****&#x20;must return the same result as&#x20;*****y.equals(x)***
* *transitive*: if *x.equals(y)* and *y.equals(z)* then also *x.equals(z)*
* *consistent*: the value of *equals()* should change only if a property that is contained in *equals()* changes (no randomness allowed)

We can look up the exact criteria in the [Java SE Docs for the *Object* class](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Object.html).

### **1.3)  Violating&#x20;*****equals()*****&#x20;Symmetry with Inheritance**

If the criteria for *equals()* is such common sense, how can we violate it at all? Well, **violations happen most often, if we extend a class that has overridden&#x20;*****equals()*****.** Let’s consider a *Voucher* class that extends our *Money* class:

![](/files/-LaVwfI40XpiWcaD_V0w)

At first glance, the *Voucher* class and its override for *equals()* seem to be correct. And both *equals()*&#x6D;ethods behave correctly as long as we compare *Money* to *Money* or *Voucher* to *Voucher*. **But what happens, if we compare these two objects?**

![](/files/-LaVwr74F4AmNNCQBrXF)

**That violates the symmetry criteria of the&#x20;*****equals()*****&#x20;contract.**

```java
package com.gs.ilp.corejava.collectionsFramework2.equalsandhashcode;

public class WrongVoucher extends Money {

	private String store;

	public WrongVoucher(String store) {
		super();
		this.store = store;
	}

	public WrongVoucher() {
		super();
		// TODO Auto-generated constructor stub
	}

	public WrongVoucher(int amount, String currencyCode, String store) {
		super(amount, currencyCode);
		this.store = store;
		// TODO Auto-generated constructor stub
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (!super.equals(obj))
			return false;
		if (!(obj instanceof WrongVoucher))
			return false;
		WrongVoucher other = (WrongVoucher) obj;
		if (store == null) {
			if (other.store != null)
				return false;
		} else if (!store.equals(other.store))
			return false;
		return true;
	}
}
```

```java
package com.gs.ilp.corejava.collectionsFramework2.equalsandhashcode;

public class TestWrongVoucher {
	public static void main(String[] args) {
		Money cash = new Money(42, "USD");
		WrongVoucher voucher = new WrongVoucher(42, "USD", "Amazon");

		System.out.println(voucher.equals(cash));
		System.out.println(cash.equals(voucher));
	}
}
```

![](/files/-Lapt1wyx58o0_AvP2rr)

### **1.4) Way 1: Using getClass instead of instanceOf()**

**Refer to** Way 1:  Using getClass()

#### Example 2:

{% embed url="<https://stackoverflow.com/questions/13162188/java-equals-method-in-base-class-and-in-subclasses>" %}

### **1.4)&#x20;*****Way 2 :*****&#x20;Fixing&#x20;*****equals()*****&#x20;Symmetry with Composition**

To avoid this pitfall, we should **favor composition over inheritance.**

Instead of subclassing *Money*, let’s create a *Voucher* class with a *Money* property:

![](/files/-LaVx5SxPBmlPrPi_hDX)

And now, *equals* will work symmetrically as the contract requires.

## **2.&#x20;*****hashCode()***

*hashCode()* returns an integer representing the current instance of the class. We should calculate this value consistent with the definition of equality for the class. Thus **if we override the&#x20;*****equals()*** method, we also have to override *hashCode()*.

For some more details, check out our [guide to *hashCode()*](https://www.baeldung.com/java-hashcode).

### **2.1)&#x20;*****hashCode()*****&#x20;Contract**

Java SE also defines a contract for the *hashCode()* method. A thorough look at it shows how closely related *hashCode()* and *equals()* are.

**All three criteria in the contract of&#x20;*****hashCode()*****&#x20;mention in some ways the&#x20;*****equals()*****&#x20;method:**

* *internal consistency*: **the value of&#x20;*****hashCode()*****&#x20;may only change if a property that is in&#x20;*****equals()*****&#x20;changes**
* *equals consistency*: **objects that are equal to each other must return the same hashCode**
* *collisions*: **unequal objects may have the same hashCode**

### **2.2) Violating the Consistency of&#x20;*****hashCode()*****&#x20;and&#x20;*****equals()***

The 2nd criteria of the hashCode methods contract has an important consequence: **If we override equals(), we must also override hashCode().** And this is by far the most widespread violation regarding the contracts of the *equals()* and *hashCode()* methods.

Let’s see such an example:

![](/files/-LaVxWX28gvCcRog1Rvf)

The *Team* class overrides only *equals()*, but it still implicitly uses the default implementation of *hashCode()* as defined in the *Object* class. And this returns a different *hashCode()* for every instance of the class. **This violates the second rule.**

Now if we create two *Team* objects, both with city “New York” and department “marketing”, they will be equal, **but they will return different hashCodes.**

### **2.3)&#x20;*****HashMap*****&#x20;Key with an Inconsistent&#x20;*****hashCode()***

But why is the contract violation in our *Team* class a problem? Well, the trouble starts when some hash-based collections are involved. Let’s try to use our *Team* class as a key of a *HashMap*:

![](/files/-LaVxjlA1wwIipOG_XtV)

We would expect *myTeamLeader* to return “Anne”. **But with the current code, it doesn’t.**

If we want to use instances of the *Team* class as *HashMap* keys, we have to override the *hashCode()*&#x6D;ethod so that it adheres to the contract: **Equal objects return the same&#x20;*****hashCode.***

Let’s see an example implementation:

![](/files/-LaVxqPvvMrgWJopV0-g)

### Example : *collisions*: **unequal objects may have the same hashCode**

```java
package com.gs.ilp.corejava.collectionsFramework2.equalsandhashcode;

public class Doctor {
	private String fName;
	private String lName;

	/**
	 * @param fName
	 * @param lName
	 */
	public Doctor(String fName, String lName) {
		this.fName = fName;
		this.lName = lName;
	}

	@Override
	public int hashCode() {
		int result = fName.hashCode() + lName.hashCode();
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Doctor other = (Doctor) obj;
		if (fName == null) {
			if (other.fName != null)
				return false;
		} else if (!fName.equals(other.fName))
			return false;
		if (lName == null) {
			if (other.lName != null)
				return false;
		} else if (!lName.equals(other.lName))
			return false;
		return true;
	}

}
```

```java
package com.gs.ilp.corejava.collectionsFramework2.equalsandhashcode;

public class TestDoctorHashcodeRule3 {
	public static void main(String[] args) {
		Doctor doctor1 = new Doctor("Mohit", "Vijay");
		Doctor doctor2 = new Doctor("Vijay", "Mohit");
		System.out.println(
				"Doctors having different objects with different values but they still can have same hashcode");
		System.out.println("Are they equal " + doctor1.equals(doctor2));
		System.out.print("Do the have same hashcode ");
		if (doctor1.hashCode() == doctor2.hashCode()) {
			System.out.println(true);
		} else {
			System.out.println(false);
		}
		System.out.println("Hashcode of doctor 1 " + doctor1.hashCode());
		System.out.println("Hashcode of doctor 2 " + doctor2.hashCode());
	}

}
```

![](/files/-LapxqDc-JusXmqI308a)

### **3. When Do We Override&#x20;*****equals()*****&#x20;and&#x20;*****hashCode()*****?** <a href="#override" id="override"></a>

**Generally, we want to override either both of them or neither of them.** We’ve just seen in Section 3 the undesired consequences if we ignore this rule.

Domain-Driven Design can help us decide circumstances when we should leave them be. For entity classes – for objects having an intrinsic identity – the default implementation often makes sense.

However, **for value objects, we usually prefer equality based on their properties**. Thus want to override *equals()* and *hashCode()*. Remember our *Money* class from Section 1: 55 USD equals 55 USD – even if they’re two separate instances.

### **4. Implementation Helpers**

We typically don’t write the implementation of these methods by hand. As can be seen, there are quite a few pitfalls.

One common way is to let our IDE generate the *equals()* and *hashCode()* methods.

Apache Commons Lang and Google Guava have helper classes in order to simplify writing both methods.

Project Lombok also provides an *@EqualsAndHashCode* annotation. **Note again how&#x20;*****equals()*****&#x20;and&#x20;*****hashCode()*****&#x20;“go together” and even have a common annotation.**

### **6. Verifying the Contracts**

If we want to check whether our implementations adhere to the Java SE contracts and also to some best practices, **we can use the EqualsVerifier library.**

Let’s add the [EqualsVerifier](https://mvnrepository.com/artifact/nl.jqno.equalsverifier/equalsverifier) Maven test dependency:

Let’s verify that our *Team* class follows the *equals()* and *hashCode()* contracts:

It’s worth noting that *EqualsVerifier* tests both the *equals()* and *hashCode()* methods.

***EqualsVerifier*****&#x20;is much stricter than the Java SE contract.** For example, it makes sure that our methods can’t throw a *NullPointerException.* Also, it enforces that both methods, or the class itself, is final.

It’s important to realize that **the default configuration of&#x20;*****EqualsVerifier*****&#x20;allows only immutable fields**. This is a stricter check than what the Java SE contract allows. This adheres to a recommendation of Domain-Driven Design to make value objects immutable.

If we find some of the built-in constraints unnecessary, we can add a *suppress(Warning.SPECIFIC\_WARNING)* to our *EqualsVerifier* call.

### **7. Conclusion**  <a href="#conclusion" id="conclusion"></a>

We should remember to:

* Always override *hashCode()* if we override *equals()*
* Override *equals()* and *hashCode()* for value objects
* Be aware of the traps of extending classes that have overridden *equals()* and *hashCode()*
* Consider using an IDE or a third-party library for generating the *equals()* and *hashCode()* methods
* Consider using EqualsVerifier to test our implementation

Finally, all code examples can be found [over on GitHub](https://github.com/mmalhotra2000/corejavatutorials).<br>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://gyansetu-core-java-for-java.gitbook.io/project/equals-and-hashcode.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
