Object-1:
Employee employee1 = new Employee("AB12","Dhruv", 24);
Object-2:
Employee employee2 = new Employee("AB12", "Dhruv", 24);
output
HASH CODE FOR EMPLOYEE 1 : 43704527
HASH CODE FOR EMPLOYEE 2 : 158893348
Object-1:
Employee employee1 = new Employee("AB12","Dhruv", 24);
Object-2:
Employee employee2 = new Employee("AB12", "Dhruv", 24);
output
HASH CODE FOR EMPLOYEE 1 : 43704527
HASH CODE FOR EMPLOYEE 2 : 158893348
Look at the following points from https://docs.oracle.com/javase/9/docs/api/java/lang/Object.html#hashCode--
Now, look at the following code and its output:
class MyEmployee {
String code;
String name;
int age;
public MyEmployee(String code, String name, int age) {
super();
this.code = code;
this.name = name;
this.age = age;
}
}
public class Main {
public static void main(String[] args) {
MyEmployee employee1 = new MyEmployee("AB12", "Dhruv", 24);
MyEmployee employee2 = new MyEmployee("AB12", "Dhruv", 24);
MyEmployee employee3 = employee1;
System.out.println(employee1.equals(employee3));
System.out.println("employee1.hashCode(): " + employee1.hashCode());
System.out.println("employee3.hashCode(): " + employee3.hashCode());
System.out.println(employee1.equals(employee2));
System.out.println("employee2.hashCode(): " + employee2.hashCode());
}
}
Output:
true
employee1.hashCode(): 511833308
employee3.hashCode(): 511833308
false
employee2.hashCode(): 1297685781
Since employee3
is pointing to the same object as employee1
, you are getting the same hashcode for them while employee2
is pointing to a different object (although it has the same content, the keyword, new
will create a separate object in the memory) and therefore, you may rarely get the same hashcode for employee2
as point#4 mentioned above from the documentation states: As much as is reasonably practical, the hashCode method defined by class Object does return distinct integers for distinct objects.
You must override hashCode
method in a way which should return the same hashcode for two objects having the same content e.g.
class MyEmployee {
String code;
String name;
int age;
public MyEmployee(String code, String name, int age) {
super();
this.code = code;
this.name = name;
this.age = age;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((code == null) ? 0 : code.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
}
public class Main {
public static void main(String[] args) {
MyEmployee employee1 = new MyEmployee("AB12", "Dhruv", 24);
MyEmployee employee2 = new MyEmployee("AB12", "Dhruv", 24);
MyEmployee employee3 = employee1;
System.out.println(employee1.equals(employee3));
System.out.println("employee1.hashCode(): " + employee1.hashCode());
System.out.println("employee3.hashCode(): " + employee3.hashCode());
System.out.println(employee1.equals(employee2));
System.out.println("employee2.hashCode(): " + employee2.hashCode());
}
}
Output:
true
employee1.hashCode(): 128107556
employee3.hashCode(): 128107556
false
employee2.hashCode(): 128107556
The implementation of hashCode
given above produces the same hashcode for employee1
and employee2
even though equals
returns false
(check as point#3 mentioned above from the documentation).
A wrong way of overriding of hashCode
may result in even the same objects returning different hashcodes e.g.
class MyEmployee {
String code;
String name;
int age;
public MyEmployee(String code, String name, int age) {
super();
this.code = code;
this.name = name;
this.age = age;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((code == null) ? 0 : (int) (code.length() * (Math.random() * 100)));
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
}
public class Main {
public static void main(String[] args) {
MyEmployee employee1 = new MyEmployee("AB12", "Dhruv", 24);
MyEmployee employee2 = new MyEmployee("AB12", "Dhruv", 24);
MyEmployee employee3 = employee1;
System.out.println(employee1.equals(employee3));
System.out.println("employee1.hashCode(): " + employee1.hashCode());
System.out.println("employee1.hashCode() again: " + employee1.hashCode());
System.out.println("employee3.hashCode(): " + employee3.hashCode());
System.out.println(employee1.equals(employee2));
System.out.println("employee2.hashCode(): " + employee2.hashCode());
}
}
Output:
true
employee1.hashCode(): 66066760
employee1.hashCode() again: 66069457
employee3.hashCode(): 66073797
false
employee2.hashCode(): 66074882
This is the wrong way of overriding hashCode
because invoking hashCode
on the same object more than once during an execution of a Java application must consistently return the same integer (check as point#1 mentioned above from the documentation).
Now, look at the following code and its output:
class MyEmployee {
String code;
String name;
int age;
public MyEmployee(String code, String name, int age) {
super();
this.code = code;
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
MyEmployee other = (MyEmployee) obj;
if (code == null) {
if (other.code != null)
return false;
} else if (!code.equals(other.code))
return false;
return true;
}
}
public class Main {
public static void main(String[] args) {
MyEmployee employee1 = new MyEmployee("AB12", "Dhruv", 24);
MyEmployee employee2 = new MyEmployee("AB12", "Dhruv", 24);
MyEmployee employee3 = employee1;
System.out.println(employee1.equals(employee3));
System.out.println("employee1.hashCode(): " + employee1.hashCode());
System.out.println("employee3.hashCode(): " + employee3.hashCode());
System.out.println(employee1.equals(employee2));
System.out.println("employee2.hashCode(): " + employee2.hashCode());
}
}
Output:
true
employee1.hashCode(): 511833308
employee3.hashCode(): 511833308
true
employee2.hashCode(): 1297685781
Since employee1.equals(employee2)
returns true
, the hashcode should also be returned same (check point#2 mentioned above from the documentation). However, the hashcode values of employee1
and employee2
are different which is not correct. This difference is because we haven't overridden the hashCode
method. So, whenever you override equals
, you should also override hashCode
in a correct way.
Finally, given below is a correct way of implementing hashCode
and equals
:
class MyEmployee {
String code;
String name;
int age;
public MyEmployee(String code, String name, int age) {
super();
this.code = code;
this.name = name;
this.age = age;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((code == null) ? 0 : code.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
MyEmployee other = (MyEmployee) obj;
if (age != other.age)
return false;
if (code == null) {
if (other.code != null)
return false;
} else if (!code.equals(other.code))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
public class Main {
public static void main(String[] args) {
MyEmployee employee1 = new MyEmployee("AB12", "Dhruv", 24);
MyEmployee employee2 = new MyEmployee("AB12", "Dhruv", 24);
MyEmployee employee3 = employee1;
System.out.println(employee1.equals(employee3));
System.out.println("employee1.hashCode(): " + employee1.hashCode());
System.out.println("employee3.hashCode(): " + employee3.hashCode());
System.out.println(employee1.equals(employee2));
System.out.println("employee2.hashCode(): " + employee2.hashCode());
}
}
Output:
true
employee1.hashCode(): 128107556
employee3.hashCode(): 128107556
true
employee2.hashCode(): 128107556
Unless you @Override
the hashCode()
method and implement your own version, your class will use the default method inherited from Object
, which generates a unique hashCode per object instance.
If you want equals
and/or hashCode
to only care about the members of the object, you'll need to write the implementations yourself.
Because you haven't overridden hashCode
to replace the default implementation. Overriding equals
doesn't change hashCode
(you almost always have to override both if you override equals
).
The hashCode
documentation says this about the default implementation in 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 Java™ programming language.)
So you'll get distinct integers (usually) for different instances, even if they're equivalent, unless you replace hashCode
.
You can do it this way
@Override
public int hashCode() {
return hashId;
}