I have a basic class with the structure:
class Employee {
int eId;
String eName;
Employee(int id, String name) {
this.eId= id;
this.eName= name;
}
The conditions for equality is such that equals()
should return true if any of the following is true:
eId
are same. eName
are same. eName
are same. I had no problem in overriding equals()
, however, in order to maintain the hash code contract, I should override hashCode()
as well. So, the hashCode should depend on eId
and eName.length()
(if eName
s are equal, their lengths will be equal as well). So there are four cases:
Employee e1 = new Employee(4, "John");
Employee e2 = new Employee(3, "Jane");
Employee e3 = new Employee(4, "Jim");
Employee e4 = new Employee(7, "Random");
hashCode()
should return the same value for e1
, e2
, and e3
and a different value for e4
. I can't come up with the logic satisfying this requirement.
Here is the exact problem:
Create a class (having parameters name, id etc). Show that if 2 objects of this class will be compared then they should return true in any of below case :
A. Id of both are same.
B. Name of both are same.
C. Length of name's of both are same.
Make sure HashCode contract should not violate.
You're running into trouble because your notion of equality is inconsistent. Specifically, it's not transitive, which the contract for .equals()
requires.
It is transitive : for any non-null reference values
x
,y
, andz
, ifx.equals(y)
returnstrue
andy.equals(z)
returnstrue
, thenx.equals(z)
should returntrue
.
Under your definition, e1
equals e2
and e3
, but e2
does not equal e3
. This is incompatible with Java's notion of equality. This is also why you're running into trouble defining a reasonable .hashCode()
implementation.
However what you can do is define a custom Comparator
(or Ordering
, if you're using Guava). For most use cases (like sorting, searching, or filtering) you should be able to use a separate Comparator
instance just like you would the .equals()
method. You are effectively trying to define equivalent objects, not equal objects.
If you can't use a separate Comparator
for whatever reason, your Employee
object will be fundamentally inconsistent, and will prove problematic even if you should get a "workable" .hashCode()
implemented.
I guess, you cannot write a consistent hashCode
in your case, because your equals
breaks the contract of Object.equals
method, namely transitivity:
It is transitive : for any non-null reference values
x
,y
, andz
, ifx.equals(y)
returnstrue
andy.equals(z)
returnstrue
, thenx.equals(z)
should returntrue
.
Suppose you have this code:
Employee a = new Employee(1, "John");
Employee b = new Employee(1, "James");
Employee c = new Employee(2, "James");
In this case with your equals operation a.equals(b)
and b.equals(c)
, but not a.equals(c)
.
I'd suggest to rethink the implementation of equals
. Probably your Employee
has either eId
or eName
defined, so it might be better to add a boolean
field which says whether eId
or eName
should be used. This way you can easily implement equals
and hashCode
. This way the implementation might be like this (assuming for simplicity that eName
cannot be null
):
class Employee {
boolean useName;
int eId = 0;
String eName;
Employee(int id) {
this.eId = id;
this.useName = false;
}
Employee(String name) {
this.eName = name;
this.useName = true;
}
@Override
public int hashCode() {
return useName ? eName.length() * 1337 : eId * 7331;
}
@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 (useName != other.useName)
return false;
if (useName) {
if (eName.length() != other.eName.length())
return false;
} else {
if (eId != other.eId)
return false;
}
return true;
}
}
If you use Java 7, then I think it's easy by using java.util.Objects:
@Override
public int hashCode() {
return Objects.hash(eld,eName.length());
}
Or you can can consider Guava , it has a same method under com.google.common.base.Objects
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.