Coming from a c++ world, I find reading of the HashSet documentation somewhat hard:
In c++, you would have:
which in turns points to:
Which makes it obvious the requirement for the type of element handled by a std::set
. My question is: What are the requirements for the type (E) of elements maintained by a Set
in Java ?
Here is a short example which I fail to understand:
import gdcm.Tag;
import java.util.Set;
import java.util.HashSet;
public class TestTag
{
public static void main(String[] args) throws Exception
{
Tag t1 = new Tag(0x8,0x8);
Tag t2 = new Tag(0x8,0x8);
if( t1 == t2 )
throw new Exception("Instances are identical" );
if( !t1.equals(t2) )
throw new Exception("Instances are different" );
if( t1.hashCode() != t2.hashCode() )
throw new Exception("hashCodes are different" );
Set<Tag> s = new HashSet<Tag>();
s.add(t1);
s.add(t2);
if( s.size() != 1 )
throw new Exception("Invalid size: " + s.size() );
}
}
The above simple code fails with:
Exception in thread "main" java.lang.Exception: Invalid size: 2 at TestTag.main(TestTag.java:42)
From my reading of the documentation only the equals operator needs to be implemented for Set:
What am I missing from the documentation ?
I just tried to reproduce your issue, and maybe you just didn't override equals and/or hashSet correctly.
Take a look at my incorrect implemenation of Tag:
public class Tag {
private int x, y;
public Tag(int x, int y) {
this.x = x;
this.y = y;
}
public boolean equals(Tag tag) {
if (x != tag.x) return false;
return y == tag.y;
}
@Override
public int hashCode() {
int result = x;
result = 31 * result + y;
return result;
}
}
Looks quite ok doesn't it? But the problem is, I actually do not override the correct equals method, I overloaded it with my own implementation.
To work correctly, equals has to look like this:
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Tag tag = (Tag) o;
if (x != tag.x) return false;
return y == tag.y;
}