Reputation: 21348
While reading about equals() and hashcode(), I came to know that if two objects are equal, then their hashcodes must be equal, though not vice-versa.
But below example doesn't reflect this.
class Employee{
private String name;
Employee(String name){
this.name = name;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Employee other = (Employee) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
Now if I create two Employee objects as
Employee e1 = new Employee("hi");
Employee e2 = new Employee("hi");
If i do, e1.equals(e2)
, it returns true even though their hashcodes are different which is evident from printing, e1.hashcode()
and e2.hashcode()
.
Can someone explain me?
Upvotes: 3
Views: 11700
Reputation: 301
You should override hashcode methode. if a class overrides equals, it must override hashCode when they are both overridden, equals and hashCode must use the same set of fields if two objects are equal, then their hashCode values must be equal as well if the object is immutable, then hashCode is a candidate for caching and lazy initialization
Upvotes: 0
Reputation: 19185
You need to override hashcode
method and provide implementation which is in contract with equals.
@Override
public int hashCode() {
return name == null ? 0 : name.hashCode();
}
equals
, it must override hashCode
equals
and hashCode
must use the same
set of fields
equal
, then their hashCode
values must be equal
as
wellimmutable
, then hashCode
is a candidate for caching
and lazy initialization
You can read about implementing hashcode here
If you don't override the method default behavior will be used from Object class.
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.)
Hash based [HashMap,HashSet,Hashtable,LinkedHashSet,WeakHashMap]
collections will use hashCode()
to find/store objects in buckets and then they will call equals()
.
Upvotes: 11
Reputation: 213371
This is because, everytime you override equals
method you must also override hashcode
method.
Else, your objects will be compared according to your code, but their HashCode will be calculated according to the pre-defined algorithm in the Object class.
NOTE: - In general, what all parameters you have considered in checking whether your objects
are equals or not, you should use all those parameters
to calculate the hashcodes
for each object
.
See this very good post which describes the use of equals
and hashcode
method.
To quote a line from this post, that I already described above: -
Use same set of fields to compute
hashcode
that you used inequals
method
Let's see the below Demo to understand the above statement: -
public class Demo {
private String str;
private String name;
public boolean equals(Object obj) {
// Suppose you compare two objects based on length of their name variable
// If name equals, object are equal
if (obj instanceof Demo) {
return this.name.equals(((Demo)obj).name);
}
return false;
}
// ****** Badly Overrided hashcode *******
public int hashcode() {
// But you calculate hashcode using both the fields
// You should never use this kind of code in hashcodes.
// Use complex algorithm which gives you distinct result for
// objects that are not equal.
return str.length + name.length;
}
}
So, If the two objects have same name
, then they would be equal, but still if their str
field has different length
, then their hashcodes
will be different.
That is why, you should always use the same fields
in equals
and hashcode
calculation.
Upvotes: 3
Reputation: 59637
You'll need to also override hashCode
to get the behavior that you expect. The default implementation of Object.hashCode
is probably returning the object references, although according to the docs this isn't required.
Without overriding hashCode
you can't expect specialized results; this is analogous to overriding equals
.
Upvotes: 0