Object equals method and hashcode Method - java

I'm revising for my upcoming exam and I've came across a question from a past paper that I'm unsure on.
The question is the following : Describe the equivalence relation that the Object equals method implements. What relationship must hold between the Object equals method and hasCode methods?
If this came up in the exam then I wouldn't be too sure how about answering this. I'll try and give it my best shot. Since the Object equals method is checking whether two objects are equal, the hashcode gives objects ascii values. If you have two objects that are the same it is possible that they can be given the same hascode since they're equal. The object equals method you are told whether they're equal whereas the hashcode method gives you a value which you can then use to compare with other hashcodes and find out whether they're the same or not. Also could have I of mentioned something about overriding methods ? I'm not if that could come into play in the answer.
My answer is probably completely wrong but the best I could think off :P

To the Java API Documentation! especially Object.hashCode
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.
This means that if the equal method returns true, hashCode must return the same value for both objects.
x.equals(y) == true => x.hashCode() == y.hashCode()
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. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.
But! If the objects are not the same they may have the same hashCode()! (But it is not advised)
The requirements for the equals() method are well described, so i won't repeat them here.

The question is clearly answered in the descriptions of both the equals() method and the hashCode() method. Have a look at equals method description and hashCode method description.
Here is the relevant answer you might be looking for:
The equals method for class Object implements the most discriminating
possible equivalence relation on objects; that is, for any non-null
reference values x and y, this method returns true if and only if x
and y refer to the same object (x == y has the value true).
Note that it is generally necessary to override the hashCode method
whenever this method is overridden, so as to maintain the general
contract for the hashCode method, which states that equal objects must
have equal hash codes.
This the hashCode method description:
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.
Also, the hashCode method does not give the ASCII value of an object, merely an integer value that uniquely defines the object.

Related

If the hashcode() creates hashcode based on the address of the object, how can two different objects with same contents create the same hashcode?

When you read the description of hashCode() in the Object class, it says that
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.
I've read an article and it says that an object's hashcode() can provide different integer values if it runs in different environments even though their content is the same.
It does not happen with String class's hashcode() because the String class's hashcode() creates integer value based on the content of the object. The same content always creates the same hash value.
However, it happens if the hash value of the object is calculated based on its address in the memory. And the author of the article says that the Object class calculates the hash value of the object based on its address in the memory.
In the example below, the objects, p1 and p2 have the same content so equals() on them returns true.
However, how come these two objects return the same hash value when their memory addresses are different?
Here is the example code: main()
Person p1 = new Person2("David", 10);
Person p2 = new Person2("David", 10);
boolean b = p1.equals(p2);
int hashCode1 = p1.hashCode();
int hashCode2 = p2.hashCode();
Here is the overriden hashcode()
public int hashCode(){
return Objects.hash(name, age);
}
Is the article's content wrong?
If there is a hashCode() that calculates a hash value based on the instance's address what is the purpose of them?
Also, if it really exists, it violates the condition that Object class's hashCode() specifies. How should we use the hashCode() then?
I think you have misunderstood this statement:
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.
The word “must” means that you, the programmer, are required to write a hashCode() method which always produces the same hashCode value for two objects which are equal to each other according to their equals(Object) method.
If you don’t, you have written a broken object that will not work with any class that uses hash codes, particularly unsorted Sets and Maps.
I've read an article and it says that an object's hashcode() can provide different integer values if it runs in different environments even though their content is the same.
Yes, hashCode() can provide different values in different runtimes, for a class which does not override the hashCode() method.
… how come these two objects return the same hash value when their memory addresses are different?
Because you told them to. You overrode the hashCode() method.
If there is a hashCode() that calculates a hash value based on the instance's address what is the purpose of them?
It doesn’t have a lot of use. That’s why programmers are strongly recommended to override the method, unless they don’t care about object identity.
Also, if it really exists, it violates the condition that Object class's hashCode() specifies. How should we use the hashCode() then?
No it does not. The contract states:
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.
As long as the hashCode method defined in the Object class returns the same value for the duration of the Java runtime, it is compliant.
The contract also says:
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.
Two objects whose equals method reports that they are effectively equal must return the same hashCode. Any instance of the Object class whose type is not a subclass of Object is only equal to itself and cannot be equal to any other object, so any value it returns is valid, as long as it is consistent throughout the life of the Java runtime.
The article is wrong, memory address is not involved (btw. the address can change during the lifecycle of objects, so it's abstracted away as a reference). You can look at the default hashCode as a method that returns a random integer, which is always the same for the same object.
Default equals (inherited from Object) works exactly like ==. Since there is a condition (required for classes like HashSet etc. to work) that states when a.equals(b) then a.hashCode == b.hashCode, then we need a default hashCode which only has to have one property: when we call it twice, it must return the same number.
The default hashCode exists exactly so that the condition you mention is upheld. The value returned is not important, it's only important that it never changes.
No p1 and p2 does not have the same content
If you do p1.equals(p2) that will be false, so not the same content.
If you want p1 and p2 to equal, you need to implement the equals methods from object, in a way that compare their content. And IF you implement the equals method, then you also MUST implement the hashCode method, so that if equals return true, then the objects have the same hashCode().
Here's the design decision every programmer needs to make for objects they define of (say) MyClass:
Do you want it to be possible for two different objects to be "equal"?
If you do, then firstly you have to implement MyClass.equals() so that it gives the correct notion of equality for your purposes. That's entirely in your hands.
Then you're supposed to implement hashCode such that, if A.equals(B), then A.hashCode() == B.hashCode(). You explicitly do not want to use Object.hashCode().
If you don't want different objects to ever be equal, then don't implement equals() or hashCode(), use the implementations that Object gives you. For Object A and Object B (different Objects, and not subclasses of Object), then it is never the case that A.equals(B), and so it's perfectly ok that A.hashCode() is never the same as B.hashCode().

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

What happening in Object.hashCode() method?

As far as I know Object.hashCode() method has native implementation. I particularly interested in: is there any randomization in this method?
I have class straight forward derived from the Object.class without redefined hashCode method. Correct me if I am wrong but when we call == operator we compare references of such objects, alias compare hashcodes.
So do we always get false
//pseudocode
new SomeObject(3) == new SomeObject(3)
because of randomization involved into Object.hashCode() method?
The Object hascode is just a hash, not a pointer. So the == will compare the references not the hashcode.
The general contract of hashCode from spec 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.
However, the programmer should be aware that producing distinct
integer results for unequal objects may improve the performance of
hash tables.
The keyword native tells the the implementation is done at native code using JNI(Java Native Interface).
Also if you are overriding the hashcode method dont forget that your implementation should satisfy the above contract else you may get wrong output, where it is used. Say HashMap class.
More info: What issues should be considered when overriding equals and hashCode in Java?
As far as I know Object.hashCode() class is native.
Correct.
I particularly interested in: is there any randomization in this method?
The hashcode returned by Object.hashCose() IS typically based on a machine address of the object at some time during its lifetime. The address, and hence the hashcode may be influenced by a variety of random factors, depending on the application.
However, this does not mean that the hashcodes are random. In fact, if you allocated two objects one after the other and immediately got their hashcodes, it is likely that there will be a strong correlation between the two hashcodes.
Likely ... but not guaranteed.
Correct me if I am wrong but when we call == operator we compare references of such objects.
Correct.
... alias compare hashcodes.
If you are saying that == involves hashcodes, that is INCORRECT. == is implemented by comparing the current machine addresses of the objects.
So do we always get false because of randomization involved into Object.hashCode() method?
No. In your example, you get false because the object references are different!
In fact, it is possible for two distinct Object instances to have the same hashcode.
o1 == o2 IMPLIES o1.hashcode() == o2.hashcode() is TRUE
o1.hashcode() == o2.hashcode() IMPLIES o1 == o2 is FALSE

understanding the relation between hashcode and equals method in Java [duplicate]

This question already has answers here:
Relationship between hashCode and equals method in Java [duplicate]
(7 answers)
Closed 8 years ago.
This is my understanding about hashcode and equals method :
if obj1.hashcode == obj2.hashcode (returns true) then obj1.equals(obj2) returns true and
if obj1.equals(obj2) returns false (returns true) then obj1.hashcode == obj2.hashcode (returns false)
is this correct?
The convention between equals() and hashCode() mandates this:
If an object is determined to be equal, then their hash code must* be equal. That is to say, if obj1.equals(obj2), then obj1.hashCode() == obj2.hashCode().
If an object is determined to not be equal, then there is no hard-and-fast rule for what their hash code should be between them. They could return the same hash code, but this may cause a multitude of errors.
*: This "must" is actually unenforceable at compile time or run time, so take it with a grain of salt. Just note that you jeopardize the correctness of your application with equals/hashCode usage if it is not implemented correctly.
if obj1.hashcode == obj2.hashcode (returns true) then obj1.equals(obj2) might return true
From the javadoc
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.
However, the programmer should be aware that producing distinct
integer results for unequal objects may improve the performance of
hash tables
That is incorrect. The documentation for Object.equals(Object) has a formal explanation of the contract for extending this method. Essentially the intent for the Object.equals method is to check if two objects are actually the same object. However it often makes sense to override this functionality and instead make your class' equals method determine whether two objects are logically equal to each other (for example, two different instances of String objects which both represent the same sentence).
On the other hand, Object.hashCode() specifies the following contract:
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.
However, the programmer should be aware that producing distinct
integer results for unequal objects may improve the performance of
hash tables.
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 Java™ programming language.)
Basically, two different objects (either logically different or technically distinct) may have the same hashcode, because of how hashcodes are designed, but they should not be "equals". However, if two objects are equal to each other, they must have the same hashcode. Similarly, an object's hashcode may only change if the object itself changes in some way.
For further reading, see the Wikipedia article on hash functions.

Relationship between hashCode and equals method in Java [duplicate]

This question already has answers here:
What issues should be considered when overriding equals and hashCode in Java?
(11 answers)
Why do I need to override the equals and hashCode methods in Java?
(31 answers)
Closed 9 years ago.
I read in many places saying while override equals method in Java, should override hashCode method too, otherwise it is "violating the contract".
But so far I haven't faced any problem if I override only equals method, but not hashCode method.
What is the contract? And why am I not facing any problem when I am violating the contract? In which case will I face a problem if I haven't overridden the hashCode method?
The problem you will have is with collections where unicity of elements is calculated according to both .equals() and .hashCode(), for instance keys in a HashMap.
As its name implies, it relies on hash tables, and hash buckets are a function of the object's .hashCode().
If you have two objects which are .equals(), but have different hash codes, you lose!
The part of the contract here which is important is: objects which are .equals() MUST have the same .hashCode().
This is all documented in the javadoc for Object. And Joshua Bloch says you must do it in Effective Java. Enough said.
According to the doc, the default implementation of hashCode will return some integer that differ for every object
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.)
However some time you want the hash code to be the same for different object that have the same meaning. For example
Student s1 = new Student("John", 18);
Student s2 = new Student("John", 18);
s1.hashCode() != s2.hashCode(); // With the default implementation of hashCode
This kind of problem will be occur if you use a hash data structure in the collection framework such as HashTable, HashSet. Especially with collection such as HashSet you will end up having duplicate element and violate the Set contract.
Yes, it should be overridden. If you think you need to override equals(), then you need to override hashCode() and vice versa. 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. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hashtables.
The contract is that if obj1.equals(obj2) then obj1.hashCode() == obj2.hashCode() , it is mainly for performance reasons, as maps are mainly using hashCode method to compare entries keys.
Have a look at Hashtables, Hashmaps, HashSets and so forth. They all store the hashed key as their keys. When invoking get(Object key) the hash of the parameter is generated and lookup in the given hashes.
When not overwriting hashCode() and the instance of the key has been changed (for example a simple string that doesn't matter at all), the hashCode() could result in 2 different hashcodes for the same object, resulting in not finding your given key in map.get().
See JavaDoc of java.lang.Object
In hashCode() it says:
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.
(Emphasis by me).
If you only override equals() and not hashCode() your class violates this contract.
This is also said in the JavaDoc of the equals() method:
Note that it is generally necessary to override the hashCode method
whenever this method is overridden, so as to maintain the general
contract for the hashCode method, which states that equal objects must
have equal hash codes.
A contract is: If two objects are equal then they should have the same hashcode and if two objects are not equal then they may or may not have same hash code.
Try using your object as key in HashMap (edited after comment from joachim-sauer), and you will start facing trouble. A contract is a guideline, not something forced upon you.

Categories