Why both hashCode() and equals() exist - java

why java Object class has two methods hashcode() and equals()? One of them looks redundant and its percolated to the bottom most derived class?

Why do you think one is redundant? They say different things:
hashCode is "give me some way of efficiently seeing whether two objects are likely to be equal"
equals is "check whether this object is genuinely equal to another"
You definitely need both - although I don't believe they should really be in Object in the first place.
You absolutely need hash codes in order to perform efficient lookups with hash tables - and you absolutely need further equality checks because hashes will collide (there are far more possible strings than hash codes, for example).

First of all, when you override equals() you MUST override hashcode() as well.
Failure to do so
will result in a violation of the general contract for Object.hashCode, which will
prevent your class from functioning properly in conjunction with all hash-based
collections, including HashMap, HashSet, and Hashtable.
Here is the contract, copied from the Object specification [JavaSE6]:
Whenever it is invoked on the same object more than once during an execu-
tion of an 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 execu-
tion of an application to another execution of the same application.
If two objects are equal according to the equals(Object) method, then call-
ing 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(Object) method, then calling the hashCode method on each of the two objects
must produce distinct integer results. However, the programmer should be
aware that producing distinct integer results for unequal objects may improve
the performance of hash tables.

The fundamental idea is that by comparing hashcode()s it's quick to check whether two objects are probably equal. If their hashcodes are equal, then the objects probably are equal (not necessarily, but it's a good guess). Then a more profound (and more expensive) check with equals() is performed. This is important to speed up all kind of look-ups (from maps etc).

equals is to compare objects, hashcode is used to generate a hash value from an object, which will then be used by the java map containers (Hashtable, Map etc).
it's common practice to override them together (if you override hashcode, you need to override equals and vice versa).

Related

What is the use of overriding hashCode in Java other than Collections API?

This question is asked by interviewer that most of answers related to hash code is used for bucketing where it checks equals to search objects.
Is there any other general use case or scenario, where hash code is beneficial and can be used in a routine program?
As recently I have used JPA where it throws exception "Composite-id class does not override hashCode()" but again it is used by implementation class of hibernate. Sly, what other places or scenario we can use hashcode other then collections especially scenario where you have used it yourself.
class a {
public int hashCode() {
}
}
class b {
public static void main(String[] str) {
//In what ways can i use hashcode here?
}
}
Let's say your class will not be used in any collection ever( which is very unlikely though), it will be used in more than one place and by other developers. Any developer using your class will expect that if two instances of that class are equal based on equals method, they should produce same hashCode value. This fundamental assumption will be broken if hashCode is not overridden to be consistent with equals and that will prevent their code to function properly.
From Effective Java , 3rd Edition :
ITEM 11: ALWAYS OVERRIDE HASHCODE WHEN YOU OVERRIDE EQUALS
You must override hashCode in every class that overrides equals. If
you fail to do so, your class will violate the general contract for
hashCode, which will prevent it from functioning properly in
collections such as HashMap and HashSet. Here is the contract, adapted
from the Object specification :
• When the hashCode method is invoked on an object repeatedly during
an execution of an application, it must consistently return the same
value, provided no information used in equals comparisons is modified.
This value need not remain consistent from one execution of an
application to another.
• If two objects are equal according to the equals(Object) method,
then calling hashCode on the two objects must produce the same integer
result.
• If two objects are unequal according to the equals(Object) method,
it is not required that calling hashCode on each of the objects must
produce distinct results. However, the programmer should be aware that
producing distinct results for unequal objects may improve the
performance of hash tables.
The key provision that is violated when you fail to override hashCode
is the second one: equal objects must have equal hash codes. Two
distinct instances may be logically equal according to a class’s
equals method, but to Object’s hashCode method, they’re just two
objects with nothing much in common. Therefore, Object’s hashCode
method returns two seemingly random numbers instead of two equal
numbers as required by the contract.
A small semantic mistake in the interview question. Hash code is not used to check equality, it's used to detect inequality. If hash codes are different the objects are guaranteed to be inequal. If the codes are equal the objects may be equal and need to be checked with the equals-method.
That said, if the hash code is cached, it could be used to speed up the equals method.
Suppose you only override equals but not hashCode
This means that hashCode is inherited from Object
Object.hashCode always tries to return different hash codes for different objects (regardless if they are equal or not)
This means that you may end up with different hash codes for two objects that you consider to be equal.
This in turn causes these two equal objects to end up in different buckets in hash based collections such as HashSet.
This causes such collections to break.
More reference: https://programming.guide/java/overriding-hashcode-and-equals.html

Why can't I just compare the hashCode of two objects in order to find out if they are equal or not?

Why do the equals methods implemented by Eclipse compare each value, wouldn't it be simpler to just compare the hashCodes of both objects?
From what I know:
hashCode always generates the same hash for the same input
So if two objects are equal, they should have the same hash
If objects that are equal have the same hash, I can just check the hash in order to determine of objects are equal or not
edit: Related question, why does one always implement the hashCode when equals is implemented, if the hashCode isn't actually needed for equals?
hashCode always generates the same hash for the same input
Correct.
So if two objects are equal, they should have the same hash
Correct.
If objects that are equal have the same hash, I can just check the hash in order to determine of objects are equal or not
Non sequitur. Objects that are unequal can also have the same hashcode. That is the purpose of a hashcode.
Related question, why does one always implement the hashCode when equals is implemented, if the hashCode isn't actually needed for equals?
Because it is needed for hashing, in HashMap, HashSet, and friends. If you think your object will never be so used, don't override it, and good luck with that.
To complement #EJP's answer, here is a perfectly valid, although useless, implementation of .hashCode():
#Override
public int hashCode()
{
return 42; // The Answer
}
Putting this in very simple terms: while every squirrel is an animal, not every animal is a squirrel. The hashCode is usually used for quick lookup - it should be efficient and it should distribute data uniformly across a lookup table - see here. But a hash function can generate collisions, which is why it shouldn't be used as a means of verifying object equality.
It's all very much dependent on the implementation of hashCode - as you can also see in fge's answer.
As to why it usually needs to be reimplemented when you override equals: they are both used when storing and retrieving objects from collections (for example a HashMap). The hashCode determines the place in the map where the object will be inserted, while equals is used to identify the object inside a collision bucket.

Hashcode and equals methods contract [duplicate]

This question already has answers here:
Why do I need to override the equals and hashCode methods in Java?
(31 answers)
Closed 7 years ago.
I know that when we override equals() method then we need to override hashcode() as well and other way around.
But i don't understand why we MUST do that?
In Joshua Bloch Book it is clearly written that we must do that, because when we deal with hash based collections, it is crucial to satisfy the Hashcode contract and I admit that, but what if I am not dealing with hash-based collections?
Why is it still required ?
Why to Override Equals ?
A programmer who compares references to value objects using the equals
method expects to find out whether they are logically equivalent, not
whether they refer to the same object .
Now coming to HashCode
Hash function which is called to produce the hashCode should return the same hash code each and every time,
when function is applied on same or equal objects. In other words, two
equal objects must produce same hash code consistently.
Implementation of HashCode provided by Object Class is not based upon logical equivalency ,
So Now if you will not override hashCode but override equals, then according to you 2 Objects are equals as they will pass the equals() test but according to Java they are not .
Consequences :
Set start allowing duplicates !!!
Map#get(key) will not return the correct value !!
and so on many other consquences..................
Data structures, such as HashMap, depend on the contract.
A HashMap achieves magical performance properties by using the hashcode to bucketize entries. Every item that is put in the map that has the same hashcode() value gets placed in the same bucket. These "collisions" are resolved by comparing within the same bucket using equals(). In other words, the hashcode is used to determine the subset of the items in the map that might be equal and in this way quickly eliminate the vast majority of the items from further consideration.
This only works if objects that are equal are placed in the same bucket, which can only be ensured if they have the same hashcode.
NOTE: In practice, the number of collisions is much higher than may be implied above, because the number of buckets used is necessarily much smaller than the number of possible hashcode values.
As per Joshua Bloch book;
A common source of bugs is the failure to override the hashCode
method. You must override hashCode in every class that overrides
equals. Failure to do so will result in a violation of the general
contract for Object.hashCode, which will prevent your class from
functioning properly in conjunction with all hash-based collections,
including HashMap, HashSet, and Hashtable.
Failing to override hashcode while overriding equals is violation the contract of Object.hashCode. But this won't have impact if you are using your objects only on non hash based collection.
However, how do you prevent; the other developers doing so. Also if an object is eligible for element of collection, better provide support for all the collections, don't have half baked objects in your project. This will fail anytime in the future, and you will be caught for not following the contacts while implementing :)
Because that is the way it is meant to be:
Whenever a.equals(b), then a.hashCode() must be same as b.hashCode().
What issues should be considered when overriding equals and hashCode in Java?
There are use-cases where you don't need hashcode(), mostly self-written scenarious, but you can never be sure, because implementations can and might be also relying on hashcode() if they are using equals()
This question is answered many times in SO, but still I will attempt to answer this .
In order to understand this concept completely, we need to understand the purpose of hashcode and equals, how they are implemented, and what exactly is this contract(that hashcode also should be overridden when equals is overridden)
equals method is used to determine the equality of the object. For primitive types, its very easy to determine the equality. We can very easily say that int 1 is always equal to 1. But this equal method talks about the equality of objects. The object equality depends on the instance variables or any other parameter (depend purely on the implementation - how you want to compare).
This equal method needs to be overridden if we want some customized comparison, lets say we want to say that two books are same if they have same title and same author, or I can say two books are equal if they have same ISBN.
hashcode method returns a hash code value of an object. The default implementation of the Object hashcode returns a distinct integers for distinct objects. This integer is calculated based on the memory address of the object.
So we can say that the default implementation of the equals method just comapres the hashcodes to check the equality of the object. But for the book example - we need it differently.
Also Equal objects must produce the same hash code as long as they are equal, however unequal objects need not produce distinct hash codes.
In case of not using a hash based collection, you can break the contract and need not to override the hashcode method - because you ll not be using the default implementations anywhere but still I would not suggest that and would say to have it as you may need it in future when you put those things in collection

Java Overriding hashCode() method has any Performance issue?

If i will override hashCode() method will it degrade the performance of application. I am overriding this method in many places in my application.
Yes you can degrade the performance of a hashed collection if the hashCode method is implemented in a bad way. The best implementation of a hashCode method should generate the unique hashCode for unique objects. Unique hashCode will avoid collisions and an element can be stored and retrieved with O(1) complexity. But only hashCode method will not be able to do it, you need to override the equals method also to help the JVM.
If the hashCode method is not able to generate unique hash for unique objects then there is a chance that you will be holding more than one objects at a bucket. This will occur when you have two elements with same hash but equals method returns false for them. So each time this happens the element will be added to the list at hash bucket. This will slow down both the insertion and retreival of elements. It will lead to O(n) complexity for the get method, where n is the size of the list at a bucket.
Note: While you try to generate unique hash for unique objects in your hashCode implementation, be sure that you write simple algorithm for doing so. If your algorithm for generating the hash is too heavy then you will surely see a poor performance for operations on your hashed collection. As hashCode method is called for most of the operations on the hashed collection.
It would improve performance if the right data structure used at right place,
For example: a proper hashcode implementation in Object can nearly convert O(N) to O(1) for HashMap lookup
unless you are doing too much complicated operation in hashCode() method
It would invoke hashCode() method every time it has to deal with Hash data structure with your Object and if you have heavy hashCode() method (which shouldn't be)
It depends entirely on how you're implementing hashCode. If you're doing lots of expensive deep operations, then perhaps it might, and in that case, you should consider caching a copy of the hashCode (like String does). But a decent implementation, such as with HashCodeBuilder, won't be a big deal. Having a good hashCode value can make lookups in data structures like HashMaps and HashSets much, much faster, and if you override equals, you need to override hashCode.
Java's hashCode() is a virtual function anyway, so there is no performance loss by the sheer fact that it is overridden and the overridden method is used.
The real difference may be the implementation of the method. By default, hashCode() works like this (source):
As much as is reasonably practical, the hashCode method defined by
class Object does return distinct integers for distinct objects. (This
is typically implemented by converting the internal address of the
object into an integer, but this implementation technique is not
required by the JavaTM programming language.)
So, whenever your implementation is as simple as this, there will be no performance loss. However, if you perform complex computing operations based on many fields, calling many other functions - you will notice a performance loss but only because your hashCode() does more things.
There is also the issue of inefficient hashCode() implementations. For example, if your hashCode() simply returns value 1 then the use of HashMap or HashSet will be significantly slower than with proper implementation. There is a great question which covers the topic of implementing hashCode() and equals() on SO: What issues should be considered when overriding equals and hashCode in Java?
One more note: remember, that whenever you implement hashCode() you should also implement equals(). Moreover, you should do it with care, because if you write an invalid hashCode() you may break equality checks for various collections.
Overriding hashCode() in a class in itself does not cause any performance issues. However when an instance of such class is inserted either into a HashMap HashSet or equivalent data structure hashCode() & optionally equals() method is invoked to identify right bucket to put the element in. same applicable to Retrival Search & Deletion.
As posted by others performance totally depends on how hashCode() is implemented.
However If a particular class's equals method is not used at all then it is not mandatory to override equals() and hashCode() , but if equals() is overridden , hashcode() must be overridden as well
As all previous comments mentioned, hash-code is used for hashing in collections or it could be used as negative condition in equals. So, yes you can slow you app a lot. Obviously there is more use-cases.
First of all I would say that the approach (whether to rewrite it at all) depends on the type of objects you are talking about.
Default implementation of hash-code is fast as possible because it's unique for every object. It's possible to be enough for many cases.
This is not good when you want to use hashset and let say want to do not store two same objects in a collection. Now, the point is in "same" word.
"Same" can mean "same instance". "Same" can mean object with same (database) identifier when your object is entity or "same" can mean the object with all equal properties. It seems that it can affect performance so far.
But one of properties can be a object which could evaluate hashCode() on demand too and right now you can get evaluation of object tree's hash-code always when you call hash-code method on the root object.
So, what I would recommend? You need to define and clarify what you want to do. Do you really need to distinguish different object instances, or identifier is crucial, or is it value object?
It also depends on immutability. It's possible to calculate hashcode value once when object is constructed using all constructor properties (which has only get) and use it always when hashcode() is call. Or another option is to calculate hashcode always when any property gets change. You need to decide whether most cases read the value or write it.
The last thing I would say is to override hashCode() method only when you know that you need it and when you know what are you doing.
If you will override hashCode() method will it degrade the performance of application.It would improve performance if the right data structure used at right place,
For example: a proper hashcode() implementation in Object can nearly convert O(N) to O(1) for HashMap lookup.unless you are doing too much complicated operation in hashCode() method
The main purpose of hashCode method is to allow an object to be a key in the hash map or a member of a hash set. In this case an object should also implement equals(Object) method, which is consistent with hashCode implementation:
If a.equals(b) then a.hashCode() == b.hashCode()
If hashCode() was called twice on the same object, it should return the same result provided that the object was not changed
hashCode from the performance point of view
From the performance point of view, the main objective for your hashCode method implementation is to minimize the number of objects sharing the same hash code.
All JDK hash based collections store their values in an array.
Hash code is used to calculate an initial lookup position in this array. After that equals is used to compare given value with values stored in the internal array. So, if all values have distinct hash codes, this will minimize the possibility of hash collisions.
On the other hand, if all values will have the same hash code, hash map (or set) will degrade into a list with operations on it having O(n2) complexity.
From Java 8 onwards though collision will not impact performance as much as it does in earlier versions because after a threshold the linked list will be replaced by the binary tree, which will give you O(logN) performance in the worst case as compared to O(n) of linked list.
Never write a hashCode method which returns a constant.
String.hashCode results distribution is nearly perfect, so you can sometimes substitute Strings with their hash codes.
The next objective is to check how many identifiers with non-unique has codes you still have. Improve your hashCode method or increase a range of allowed hash code values if you have too many of non-unique hash codes. In the perfect case all your identifiers will have unique hash codes.

Two instances having the same hashcode but not equal

I was reading the paragraph quoted below from an article entitled- Java theory and practice: Hashing it out - Defining hashCode() and equals() effectively and correctly
Defining equality
The Object class has two methods for making inferences about an object's identity: equals() and hashCode(). In
general, if you override one of these methods, you must override both,
as there are important relationships between them that must be
maintained. In particular, if two objects are equal according to the
equals() method, they must have the same hashCode() value (although
the reverse is not generally true).[emphasis added by me]
My question relates to the latter bit of the paragraph "although the reverse is not generally true". How is it possible for two different instances of a class to have the same hashCode but not be equal?
In simple terms hashcode () is a function to generate hash by some formula, so there can be some collisions, two different values can turn out to have same hashcode.
If I simply calculate the hashcode by taking mod by 6, then two different values might be having same hashcode.
You can consider hashes to be a bucket..
If two objects are equal, they will go into the same bucket (have same hashcodes)
But, if the two objects go into the same bucket (have same hashcode), that doesn't mean that they must be equal
Also note that, if two objects are not equal, even then they can have the same hash code.. Obviously, this infers from the above two points..
So, hashcode is nothing but the hash-value for that Bucket.. Any number of objects can have same hashcode, depending upon the algorithm used to calculate the hashcodes..
An ideal algorithm is the one, which generates different hashcodes for different objects. So, there is ideally 1 object per bucket.. Of course this is the perfect case, which might not be possible..
A bucket may of course contain several objects, based on some property..
Think of hashcode as something that just reduces the effort in checking equality.
If two objects are equal they will definitely have the same hashcode. However if two objects have the same hashcode, they might have a mathematically high similarity but still not be the same. Just for mindset: Think of comparing a duck to an elephant in a zoo. They are highly dissimilar and will have different abstract hashcode, so you dont have to bother comparing their legs, wings etc to check if they are same. However if you are comparing a duck and a swan, they are highly similar and have same abstract hashcode, so now you are down to comparing very minute features of each animal to check for equality. As you reduce the extremeness between two elements being compared, the abstract hashcode becomes more and more concrete. Like comparing ducks and swans has more concrete hashcode than comparing ducks and elephants, comparing different breed of ducks makes the hash code even more concrete, comparing dna of two ducks of same breed makes the hashcode even more concrete. This answer is just designed to create a mindset to understand concept of hashcode. After reading this, you must blur out the understanding of the word hashcode in context of this answer.
I think the reverse is actually
if two objects are NOT equal according to the equals() method, they must
have the A DIFFERENT hashCode() value
which clearly does not hold since generating unique hashes in the general case is not possible because you're usually trying to map a set of values onto a set of hash codes of lower cardinality.
I will explain it using example. Let's say that hashCode() of string is based on the string length. In this case the hash code of "foo" and "bar" are equal. But "foo" itself is not equal to "bar".
It is because has code implements a kind of formula: you can determine has code for each object but cannot restore object from hash code. There can be several objects with same hash code.
You can define your hashCode() implementation to always return 1 fore example. This is perfectly valid: Different instances (which are not equal) can have the same hashCode. But the runtime performance of looking up these objects in HashMaps, Sets or other types of collections will be very poor (because they all land in the same bucket internally - the lookup performance degrades from O(1) to O(n) because you need to traverse the list of objects in the same bucket).
Also consider taking a look at how HashMaps work in Java.
A hash code of an object is usually much smaller than the original object. This is one purpose of the hash function. So you can imagine, that if you have n different objects (say all permutations of a class) it is not possible to code them in m (where m < n) different and smaller (than the original object) unique codes.
Let me show with an example:
suppose that the HashCode of a string obtains as follow: hashCode = sum of each character ASCII code (but we know, real hash is more complicated)
For example : hash code of "abc" calculate in such form : 49+50+51 = 150
Then hash code of "acb" equals : 49+51+50 = 150
And so on. as you can see, there are many strings having hashcode=150 but they are not equal.

Categories