In last article, we saw the implementation of Hashtable. Before moving on to HashMap and its implementation let’s get to know about two primary and most used methods by java developer: equals() and hashCode(). These methods are also underlying core for both Hashtable and HashMap.
public boolean equals(Object obj)
public int hashCode()
Both methods are part of
Object class in java. This is the root of the class hierarchy. Every class has
Object class as a superclass. All objects, including arrays, implement the methods of this class.
As per Javadoc
equals()method indicates whether some other object is “equal to” given object. The default implementation of this method provided by Object class checks if two object references point to the same memory location, this comparison is known as a shallow comparison. It is called shallow comparison because the class doesn’t have any data members thus, comparison only happens on given objects references. The sub-class have their own implementation of this method as they need data member or state of the object also to be compared, such comparison is known as deep comparison.
equals() method implements an equivalence relation i.e reflexive, symmetric, transitive, consistent (refer Javadoc for these properties elaboration). One important point about this function is that whenever any object is compared against
null it always returns false and not NullPointerException.
As per Javadoc
hashcode() method returns a hash code value as an integer for the object. Hashcode value is mostly used in hashing based collections like Hashtable, HashMap, HashSet, etc. Whenever this method is invoked on the same object it should always return in the same value of integer unless the state of the object has changed or it might not be same between multiple executions of the application.
Let’s talk about the equals() and hashCode() contract:
1. If two objects are depicted equal by equals() method then there hashcode must be same.
2. If two objects are not equal by equals() method then there hashcode could be same or different.
So in simple terms, the contract is that if
obj1.hashCode() == obj2.hashCode()
So, it is generally necessary to override the
hashCode() method whenever
equals() method is overridden, so as to maintain the above contract. Let’s see how to override these methods. Few points to note before overriding these methods respectively:
this(i.e current object reference) check: if yes then return true.
nullcheck: if yes then return false.
getClass()check: verify the class of object on which method is invoked is the same as that of being compared to.
instanceofcan also be used for immutable class but for others it can’t be used as it returns true if the object is an instance of a subclass.
- Do not typecast the object with which comparison is being done: note the sequence
instanceofcheck must be done prior to casting object. Always remember overriding and overloading are not the same. So as object class defines
public boolean equals(Object o)don’t change the arg to your own class type e.g:
public boolean equals(Test t).
- Compare attributes of the object starting with numeric attribute because comparing numeric attribute is fast and use logical operators for combining checks. If the first field does not match, return false. It’s also worth to remember doing
nullcheck on individual attributes before calling
equals()method on them recursively to avoid NullPointerException during the check.
- Last but not least, do not forget to override the
Points to remember while overriding
- Do check
null: Before calling the method on members or fields to avoid NullPointerException, remember to check null if a member is null then return zero.
- Do keep the return of
- Do cache the hashcode for immutable objects leads to improved performance.
If you don’t override method properly your Object may not function correctly on hash-based collections, always tries to use effective hashcode implementation. IDEs like Eclipse, IntelliJ Idea provide the implementation use them as they are generally good enough to generate good hash code. For IntelliJ Idea, one can press
command + N(Code -> Generate) and choose the
Now, we know things to ponder before overriding let’s take a look at an example, in the below code I have used IntelliJ Idea to override these methods for me.
Few quirks of these functions:
- Equal objects must produce the same hash code as long as they are equal, however unequal objects may not produce distinct hash codes.
- String and wrapper classes like Integer, Float and Double override
equals()method but StringBuffer doesn’t override it.
- While comparing objects always prefer
equals()as it does deep comparison rather than
==shallow comparison(behavior of Object class
equals()also, especially for
- From Java 7 we can also use a new utility class called java.util.Objects for
nullsafe equality check and calculating hashcode. e.g:
int exampleHashCode = Objects.hash(example1);
instanceofcheck breaks symmetric property of
subClass instanceof ParentClassis true but
ParentClass instanceof subClassis false. Thus, the symmetric property if
a equals bthen
b equals ais broken.
In next article, we’ll look into HashMap as promised earlier :)
Why do I need to override the equals and hashCode methods in Java?
Asked Recently I read through this Developer Works Document. The document is all about defining hashCode() and equals()…
Java instanceof Operator | Baeldung
In this quick tutorial, we'll learn about the instanceof operator in Java. instanceof is a binary operator used to test…