Tim*_*imo 6 java collections set
我使用CopyOnWriteArraySet来存储自定义类的一个实例,如下所示:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
当我打印套装时,一切似乎都可以:
MyClass theObject = new MyClass("Object 1");
CopyOnWriteArraySet<MyClass> theSet = new CopyOnWriteArraySet();
theSet.add(theObject);
for (MyClass tmp : theSet){
System.out.println(tmp.toString());
}
Run Code Online (Sandbox Code Playgroud)
结果是:
对象1
所以,显然对象在集合中.
现在,我想从集合中删除对象:
theSet.remove(theObject);
Run Code Online (Sandbox Code Playgroud)
然后我再次打印该集的内容.结果:
对象1
很奇怪.所以,我试过这个:
System.out.println(String.valueOf(theSet.contains(theObject)));
Run Code Online (Sandbox Code Playgroud)
结果:
假
显然,theObject虽然它在那里但是找不到.所以,我想,这个equals()方法有问题.因此,我更改了方法覆盖equals()并hashCode()通过向每个函数的第一行添加控制台打印:
@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);
}
Run Code Online (Sandbox Code Playgroud)
然后,我再次打电话:
theSet.remove(theObject);
Run Code Online (Sandbox Code Playgroud)
结果:
hashCode()调用
那么,该equals()方法根本不被调用?
有人可以解释那里发生了什么吗?
我已经尝试比较theObject集合中的hashCodes 和实例,它们都是相等的.
我找到了问题的原因。
我正在使用 Hibernate,它创建了一个自己的 org.hibernate.collection.PersistentSet 实例,它取代了我的 CopyOnWriteArraySet!
.contains() 和 .remove() 不起作用的事实是 Hibernate 中的一个错误:http://opensource.atlassian.com/projects/hibernate/browse/HHH-3799
我的例子的解决方案是不重写.hashCode() 方法。
注意:这可能不是适合所有情况的最佳解决方案。对我来说,它确实有效。在上面的链接中,描述了几种解决方法。