无法在Java';中删除或找到对象;s CopyOnWriteArraySet
我使用CopyOnWriteArraySet存储自定义类的一个实例,如下所示:无法在Java';中删除或找到对象;s CopyOnWriteArraySet,java,collections,set,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
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());
}
然后我再次打印集合的内容。
结果是:
对象1
很奇怪。所以,我试过这个:
System.out.println(String.valueOf(theSet.contains(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()
因此,根本不调用equals()
方法
有人能解释一下那里发生了什么事吗
我已经尝试比较对象和集中实例的hashCode,它们都相等。HashSet使用hashCode,但是CopyOnWriteArraySet不是HashSet(也不是TreeSet),也不调用hashCode()。如果正在调用hashCode,则不使用此集合
这很奇怪,因为我无法重现你的问题
MyClass theObject = new MyClass("Object 1");
CopyOnWriteArrayList<MyClass> theSet = new CopyOnWriteArrayList();
// OR
CopyOnWriteArraySet<MyClass> theSet = new CopyOnWriteArraySet();
theSet.add(theObject);
System.out.println("After add.");
System.out.println(theSet);
theSet.remove(theObject);
System.out.println("\nAfter remove");
System.out.println(theSet);
即使我将哈希代码更改为
public int hashCode() {
throw new UnsupportedOperationException();
}
它得到相同的结果,因为这些类不使用hashCode()(hashCode()方法除外)奇怪..我已经测试了您的代码。它在我的环境中运行良好。 并且remove操作不调用hashCode(),而是调用equals()。
我使用的jdk是1.6.0_23。我找到了问题的原因 我正在使用Hibernate创建自己的org.Hibernate.collection.PersistentSet实例,该实例替换了我的CopyOnWriteArraySet .contains()和.remove()不起作用是Hibernate中的一个错误: 在我的例子中,解决方案是不重写.hashCode()方法 注意:这可能不是所有情况下的最佳解决方案。但对我来说,它奏效了。
在上面的链接中,介绍了几种解决方法。问题标题是
CopyOnWriteArraySet
,但代码是CopyOnWriteArraySet
。你到底在用什么?remove()
返回什么值-如果为false,列表中不包含该元素。如果您想要一个集合以避免重复项目,请使用CopyOnWriteArraySet
@Matt Ball抱歉,我的错误。我更正为CopyOnWriteArraySet。remove()返回false。然后集合认为它不包含您试图删除的元素。@Matt Ball是的,我知道,因为我已经发布了:setSet.contains(theObject)
返回false。问题是:为什么?嗯,我发布的代码只是我真实代码的简化版本,我不能在这里发布,因为它非常复杂和冗长。但是,由于您无法重现该问题,我假设原因一定在我的“复杂”代码中的某个地方。我只是不明白为什么它对我不起作用,为什么不调用equals()。Set如何在不使用equals()的情况下确定内部是否存在对象?@valmar-尝试用一个不太简化的代码版本自己重现问题。如果问题仍然存在,请进一步简化。执行此操作,直到您找到问题所在,或者您有一个足够简单的示例来演示问题,您可以将其发布到此处供其他人尝试。@valmar,HashSet使用hashCode,但是CopyOnWriteArraySet不是HashSet(也不是TreeSet),也不是调用hashCode()。如果正在调用hashCode,则您没有使用此集合。您是对的!我正在使用Hibernate创建自己的org.Hibernate.collection.PersistentSet实例,该实例替换了我的CopyOnWriteArraySet!非常感谢。至少,现在我知道怎么了。如果你将你的评论作为一个真实的答案发表,我会很高兴地将其标记为“正确答案”。我还发现了.remove()和.contains()失败的原因。原因是Hibernate中的一个bug干扰了.hasCode()方法(有关更多信息,请参阅我对这个问题的回答)。
After add.
[Object 1]
After remove
[]
public int hashCode() {
throw new UnsupportedOperationException();
}