集合无法在Java的CopyOnWriteArraySet中删除或找到对象
我使用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;
}
}
当我打印集时,一切似乎都正常:
MyClass theObject = new MyClass("Object 1");
CopyOnWriteArraySet<MyClass> theSet = new CopyOnWriteArraySet();
theSet.add(theObject);
for (MyClass tmp : theSet){
System.out.println(tmp.toString());
}
结果是:
Object 1
所以,很明显,对象在集合中
现在,我想从集合中删除对象:
theSet.remove(theObject);
然后我再次打印集合的内容。 结果是:
Object 1
很奇怪。所以,我试过这个:
System.out.println(String.valueOf(theSet.contains(theObject)));
结果是:
false
显然,集合无法找到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);
}
然后,我再次呼吁:
theSet.remove(theObject);
结果是:
hashCode() called
那么,根本不调用equals()
方法
有人能解释一下那里发生了什么事吗
我已经尝试比较了theObject
的hashcode和集合中的实例,它们都是相等的
# 1 楼答案
奇怪。。我已经测试了你的代码。它在我的环境中运行良好。 移除操作不调用hashCode(),而是调用equals()。 我使用的jdk是1.6.0_23
# 2 楼答案
我找到了问题的原因
我正在使用Hibernate创建自己的org实例。冬眠收集PersistentSet取代了我的CopyOnWriteArraySet
事实是。包含()和。remove()不起作用是Hibernate中的一个错误:http://opensource.atlassian.com/projects/hibernate/browse/HHH-3799
在我的案例中,解决方案是不覆盖。hashCode()方法
注意:这可能不是所有情况下的最佳解决方案。但对我来说,它奏效了。 在上面的链接中,描述了几种变通方法
# 3 楼答案
HashSet使用hashCode,但是CopyOnWriteArraySet不是HashSet(也不是TreeSet),也不是调用hashCode()。如果正在调用hashCode,则不使用此集合
这很奇怪,因为我无法重现你的问题
印刷品
即使我把hashCode改为
由于这些类不使用hashCode()(除了在hashCode()方法中),所以它会得到相同的结果