I use CopyOnWriteArraySet to store one instance of a custom class, which looks like this:
public class MyClass{
String _name;
public MyClass(String name){
_name = name;
}
@Override
public int hashCode(){
return _name.hashCode();
}
@Override
public boolean equals(Object obj){
if (obj == this) return true;
if ((obj instanceof MyClass) == false) return false;
MyClass otherObject = (MyClass) obj;
return _name.equals(otherObject._name);
}
@Override
public String toString(){
return _name;
}
}
When I print the set, everything seems ok:
MyClass theObject = new MyClass("Object 1");
CopyOnWriteArraySet<MyClass> theSet = new CopyOnWriteArraySet();
theSet.add(theObject);
for (MyClass tmp : theSet){
System.out.println(tmp.toString());
}
The result is:
Object 1
So, obviously the object is in the set.
Now, I want to remove the object from the set:
theSet.remove(theObject);
Then I print the content of the set again.
The result:
Object 1
Very weird. So, I tried this:
System.out.println(String.valueOf(theSet.contains(theObject)));
The result:
false
Obviously, the set cannot find theObject although it’s there.
So, I thought, there’s something wrong with the equals() method.
Thus, I changed the method overrides of equals() and hashCode() by adding a console print to the first line of each function:
@Override
public int hashCode(){
System.out.println("hashCode() called");
return _name.hashCode();
}
@Override
public boolean equals(Object obj){
System.out.println("equals() called");
if (obj == this) return true;
if ((obj instanceof MyClass) == false) return false;
MyClass otherObject = (MyClass) obj;
return _name.equals(otherObject.name);
}
Then, I call again:
theSet.remove(theObject);
The result:
hashCode() called
So, the equals() method isn’t called at all?
Can someone explain what’s going on there?
I already tried to compare the hashCodes of theObject and the instance inside the set and they’re both equal.
I found the reason for the problem.
I’m using Hibernate which creates an own instance of org.hibernate.collection.PersistentSet which replaced my CopyOnWriteArraySet!
The fact that .contains() and .remove() didn’t work was a bug in Hibernate: http://opensource.atlassian.com/projects/hibernate/browse/HHH-3799
The solution in my case was to not override the .hashCode() method.
Note: This might not be the best solution for all cases. For me, it worked though.
In the link above, there are several workarounds described.