So far we have learnt, when an object is added to the HashSet using the add()
method, it doesn't get added to the end of the HashSet.
But the hash code is calculated by java and the object is added to that particular location based on the HashCode.
i.e. If the HashCode of 'object1' is 6. It will get added to the 6th location of memory. Similarly if the HashCode of 'object2' is 3, it will get added to the 3rd location of memory. And if there is an object 'object3' which also has the HashCode 6, that will result in a Hash collision. So 'object3' will be added to the 6th location, just below 'object1'.
It's because if there is a collision a LinkedList is formed from that location.i.e. In 6th location there is a collision, so a LinkedList is created from the 6th location and 'Object1' and 'Object3' is added to the List.
It's calculated based on object's memory location.
So, whenever a new object is added to the HashSet, the Hash Code of that object is calculated by java and is put in the respective location(Same as the above example of object1, object2, object3).
Now, when the object is to be retrieved using the get() method, the Hash Code is again calculated by java and java reaches that particular location to fetch the object.
Just like the above case, if you provide 'Object2' to the contains() method of HashSet. Java will calculate the HashCode of 'Object2' and fetch the object from the 3rd location.
But if you ask java to retrieve 'Object3', the contains() method will calculate the Hash Code using hashCode() method and reach the 6th location.
But there are two objects in 6th location.
In this case java uses the equals() method to check each and every objects until it finds 'Object3'.
Now, the point to note is, there is a method hashCode() in java.lang.Object, which takes care of generating the hash code for objects until there is a situation where we have to calculate the hash code all by ourselves.
And just remember there is no get() method for HashSet. Because it makes no sense in case of HashSet.
So, lets take the Human example to understand the following:
We know there is a Human object with 'age' and 'name' as attributes.
Now, lets create Human objects and add it to the HashSet.
So, what we have done in the above example is:
1) Created three Human objects
2) Declare a HashSet and add the Human objects to the HashSet.
3) We are creating a new object 'human4' for holding the details of 'Paul'.
4) We have added the object 'human4' to the hashSet.
But 'human4' contains the details of 'Paul' whose age is '42'. And if we see closely 'Paul' is already in the hashSet, since we have already added 'human2' object.So, the duplicate entry is getting inserted in the HashSet. But why?
Let's understand the cause:
Set has a contains() method, which again takes the help of equals() method to check for duplicates.
And if you remember equals() compares the objects by reference. i.e. By its memory location.
Now, when we are trying to insert an object('human4' in the above case), java takes the help of equals() method to check by the memory location of the object.
In simple words the equals() method does not check what is stored inside the Object. It only checks if two objects belongs to the same memory location.
The Solution is, we have to override hashCode() and equals() method in our class.
Let us redefine the hashCode() and equals() in the Human class.
We have redefined the equals() method where we have mentioned that the objects should be compared based on value and not on memory location.
Also we have overridden the hashCode() method and put a custom logic. So that the hash code is calculated not based on the memory location(Since the default implementation of hashCode() calculates the hash code based on the memory location).