How to override equals(), hashCode() & toString() Java methods
Overview
In this blog, we will see how we can override the 3 most common and useful methods of the java Object class. We will see how equals()
& hashCode()
are related to each other. Besides this, we will see the usefulness of toString()
.
Methods Class
java.lang.Object
Also read : Why should we override equals() & hashCode()
Override equals()
Let's see how we can override equals()
to make it avoid considering the object instances.
Syntax :
public boolean equals(Object o){...}
Code Example :
public class Test {
public static void main(String[] args) {
Bank b1 = new Bank("Harsh",999);
Bank b2 = new Bank("Harsh",999);
System.out.println(b1.equals(b2));
System.out.println(b2.equals(b1));
}
}
class Bank{
String customerName;
int accountBalance;
public Bank(String name , int balance){
customerName = name;
accountBalance = balance;
}
@Override
public boolean equals(Object o){
if(o == this){
return true;
}
if(!(o instanceof Bank)){
return false;
}
Bank bank = (Bank)o;
return Objects.equals(this.accountBalance,bank.accountBalance) &&
Objects.equals(this.customerName,bank.customerName);
}
}
Output :
true
true
In the above code snippet, we have successfully overridden the equals method using the given syntax.
equal() Contract
The equal()
method performs the equivalence operation on the non-null object references.
reflexive
b1.equals(b1); //It should return true
symmetric
b1.equals(b2); //if this is returning true b2.equals(b1); //this should also return true
transitive
b1.equals(b2); //if this is returning true b2.equals(b3); // and this is also returning true b1.equals(b3); // then this should also return true
consistent : It means that the value of
equals()
changes only if any value of b1 or b2 is changed.
For detailed explanation see : Java Docs
Override hashCode()
The hashCode()
returns an integer representing the current instance or object of the class. This value should be consistent with the definition of class equality(if two objects are having same data values then they should be equal to each other irrespective of their instances). Thus, if we are overriding the equals() method, we must have to override hashCode().
Syntax :
public int hashCode() {...}
Simple hashCode() Implementation :
@Override
public int hashCode() {
return 1; //it will be hard coded and return the same hashcode even for unequal objects, it is not practical.
}
Improved hashCode() Implementation :
@Override
public int hashCode() {
return (int) id + name.hashCode() + email.hashCode();
}
IntelliJ IDE's Implementation :
@Override
public int hashCode() {
return Objects.hash(customerName, accountBalance);
}
hashCode() Contract
During one execution of the Java Application, no matter how many times we call hashCode() on an object it should return the same int value every time. This value may be different during another execution of the application.
public class codeTest { public static void main(String[] args) { Bank b1 = new Bank("Harsh",999); System.out.println(b1.hashCode()); System.out.println(b1.hashCode()); System.out.println(b1.hashCode()); } }
Output : -2140575014 -2140575014 //same -2140575014 //same
If calling
equals()
is return true on 2 different objects i.e., when two objects are the same then calling hashCode() on these two objects should return the same value.public class Test { public static void main(String[] args) { Bank b1 = new Bank("Harsh",999); Bank b2 = new Bank("Harsh",999); System.out.println(b1.equals(b2)); System.out.println(b1.hashCode()); System.out.println(b2.hashCode()); } }
Output: true -2140575014 -2140575014 //if true , then b2 value should be the same as b1
Two unequal objects may have the same hashCode value. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.
Additional Notes
Generally, we override either both of them or neither of them. If we are overriding only one of them then it will prevent your class from functioning properly in conjunction with all hash-based collections, including HashMap, HashSet, and Hashtable.
Override toString()
This is a simple yet useful method for getting the string value of an object. String values are more understandable and human-readable than the object's hashcode we can log this value for code debugging purposes.
Syntax:
public String toString() {...}
Default Implementation :
getClass().getName() + '@' + Integer.toHexString(hashCode())
Simple toString() implementation:
@Override
public String toString(){
return "Name : " + this.customerName + " , Balance : " + this.accountBalance;
}
Output :
Name : Harsh , Balance : 999
IntelliJ's IDE implmentation:
@Override
public String toString() {
return "Bank{" +
"customerName='" + customerName + '\'' +
", accountBalance=" + accountBalance +
'}';
}
Output :
Bank{customerName='Harsh', accountBalance=999}
Also, read my blog : Violation and fixation of equals() & hashCode()
Conclusion
We learned, how to override
equals()
,hashCode()
&toString()
.Always override hashCode() , if we are overriding equals()
We can consider IDE-generated implementation of these methods(preferred choice).