Reputation: 15
Sets care about uniqueness, so while implementing set in our program we must override the java.lang.Object
equals()
and hashCode()
method, so that we do not end up with duplicates. A reference holds its validity within the context of the single and current instance of the JVM, keeping this in mind I tried to code my program this way. Within TestSet.main
(lines 4-6). I have tried to put my query in a practical way by using comments in those lines.
class TestCase {
transient private int x;
private int y;
public TestCase(int x, int y) {
this.x = x;
this.y = y;
}
public boolean equals(Object o) {
if (o instanceof TestCase && (((TestCase) o).getXValue() == getYValue()))
return true;
else
return false;
}
public int hashCode() {
return x + y;
}
public int getXValue() {
return x;
}
public int getYValue() {
return y;
}
}
class TestSet {
public static void main(String[] args) {
TestCase tc1 = new TestCase(4, 8);
TestCase tc2 = new TestCase(4, 8);
Set<TestCase> set = new HashSet<TestCase>();
set.add(tc1);//succeeds
set.add(tc2);//succeeds
System.out.println(set.add(tc2));//fails and gives us false.
tc2 = new TestCase(4, 8);
System.out.println(set.add(tc2));//succeeds and gives us true?
System.out.println(set.size());
System.out.println(set.contains(tc1));
System.out.println(set.contains(tc2));
}
}
Upvotes: 1
Views: 59
Reputation: 5065
First you better fix or remove your equals method completely. Your situation has nothing to do with how hashCode method is working, I will explain how it works below:
// Set is looking for tc2 and finds object with same ref, because of previous set.add(tc2);
System.out.println(set.add(tc2));//fails and gives us false.
// You create new object with new reference.
tc2 = new TestCase(4, 8);
// Yes, because you changed tc2 variable and assigned new reference to it.
System.out.println(set.add(tc2));//succeeds and gives us true?
Upvotes: 0
Reputation: 198581
You have a typo in your equals method: you are comparing one element's x
to the other's y
. This makes pretty much no sense; you should be comparing both x's and both y's.
You should implement equals
as
return o instanceof TestCase
&& ((TestCase) o).getXValue() == getXValue()
&& ((TestCase) o).getYValue() == getYValue();
The reason the second .add(tc2)
returns false
is because HashSet
's implementation uses a ==
check as an optimization, and that happens to catch that particular case. That doesn't change the brokenness of your .equals
method.
Upvotes: 2
Reputation: 207026
The rule that equals
and hashCode
must conform to is: if two objects are equal, then their hash codes must be the same.
Note that this does not mean the opposite: if two objects have the same hash code, it does not necessarily mean that the objects are equal.
Your code violates this rule, so you get unpredictable results when you put those two objects in a HashSet
.
Upvotes: 0