Skip to main content

Understanding Equals and hashCode contract,and what can go wrong

SO what about Equals and hashcode?
Most people will say these are the two basic function available in Object class and could be called from any Class object created in Java. Well thats true but there is more then this.
First take a look at HashCode:
Every JVM provides a good hashCode implementation mostly based on the object's memory location and for two different object(by location) it produce different hashCode.
And at the same time Equal method also consider two different memory location object as Not Equal. So at core two are in a contract and works great.

But as soon as start writing code and write a class and create a state of a class(means create few data variables in a class), the core contract of hashCode and Equal doesnt work any more.
e.g.


Class MyFirstCLass{
int value;
public MyFirstCLass(int value){
this.value = value;
}
}

MyFistCLass obj1 = new MyFirstCLass(10);
MyFistCLass obj2 = new MyFirstCLass(10);


Now obj1 and obj2, theoratically should be equal as both holds the same value. Bu the basic implemenataion of equals method in java will say they are not and hashCode will also produce different hashCode value for them(basically confirms that they are not same)

Now i write following code for hash based collection.

Set mySet = new HashSet();
mySet.add(obj1);

now if i do following
mySet.contains(obj2) //see obj2 and not obj1
it returns false and basically my code doesnt work.

So then we say ok we need to write our own hashCode method, because above code should have worked.
Now Java has said that you should and can implement hashCode and Equal functions but there are few rules you should take care of
    The equals method implements an equivalence relation:
  • It is reflexive: for any reference value x, x.equals(x) should return true.
  • It is symmetric: for any reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
  • It is transitive: for any reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
  • It is consistent: for any reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the object is modified.
  • For any non-null reference value x, x.equals(null) should return false.
 and The general contract of hashCode is:
  • Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
  • If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
  • It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results.
If you want to squeeze out one sentence out of everything i have written then contract between two is
Equal objects must produce the same hash code as long as they are equal, however unequal objects need not produce distinct hash codes.
(Note:  However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hashtables.)


Things to consider when writing equal method
  1. Always check if they are at same memory location by using == operator on two objects
  2. Two different class objects can not be considered equals, so always check if passed object is instance of same class.
  3. Then compare object's property and see if they are equal.
  4. Even if you are 100% sure that your hashCode returns unequal hashCode for unEqual object, still never use it here from performance point of view.
What happens when hashCode and equals break contracts
  1. hashCode return same Value for un equal object. The performance of hashBased collection will go down as there will be more collision.
  2. hashCode return different Value for equal objects. You may not be able to find the exisitng object from hash based collection.



Comments

Popular posts from this blog

How to add custom user attributes in keycloak and access them in spring boot application

Sometime it may be possible you want to add more parameters to standard registration page of keyloak for your users and aaccess that data in your spring boot application. This artical will show step by steps on how to add such extra attributes. What is Keycloak Keycloak is an open source software product to allow single sign-on with Identity Management and Access Management aimed at modern applications and services, to learn more visit  h ttps://www.keycloak.org/ What is Spring boot Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can "just run". To learn more visit  https://spring.io/projects/spring-boot To add an extra attribute in keyclkoak server you will need to edit actuall html template and then registaer new attribute in json response so that it will be available on client. Edit HTML template Lets assume we want to add mobile number on default registration page. Go to Keycloak home installation directory edit fil

How to create java maven project in intelij

Open intellij Create a new java maven project in intellij . Select Maven type, Select JDK you want to use and click Next. Enter GroupId and ArtifactId, click Next Select project Location and click finish Intelij will display a warning, just press Ok. Once project is created , a popup may appear asking for auto import, select "Enable Auto Import" You will have a project created, looking something like this Note: I have created these instructions using, Instruction for other OS or intellij Version shouldn't be much different, if you need instruction for other version leave a comment and i will try to come up with another set of instructions. Intellij 2017.2.1 Java 1.8 Mac OS

How to git without finger print confirmation

In this article i will explain how you can run git clone command on a machine without having to accept sh key finger prints manually. Lets you want to write a script to initialise a developer machine, which require you to git clone various projects from gitlab or github or any other git repo. First time you run a git clone command, it will ask you if you accept the signature and it need to be part of automated script, its not nice thing to have. Here is the solution. First you download the git host's key then create its finger print then check this finger print against known valid finge rprint If its good then move downloaded ssh key to ~/.ssh/known_hosts file else throw error ssh-keyscan github.com >> githubKey ssh-keyscan gitlab.com >> gitlabKey export githubfinger=$(ssh-keygen -lf githubKey) export gitlabfinger=$(ssh-keygen -lf gitlabKey) echo $githubfinger echo $gitlabfinger if [[ $githubfinger == *"nThbg6kXUpJWGl7E1IGOCspRomTxdCARL