我使用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());
}
结果是:
对象1
所以,显然对象在集合中。
现在,我想从集合中删除对象:
theSet.remove(theObject);
然后我再次打印该集的内容。 结果:
对象1
非常奇怪。所以,我试过这个:
System.out.println(String.valueOf(theSet.contains(theObject)));
结果:
假
显然,该集合找不到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()
方法根本没有被调用?
有人可以解释那里发生了什么吗?
我已经尝试比较theObject
的hashCodes和集合中的实例,它们都是相等的。
答案 0 :(得分:1)
奇怪......我已经测试了你的代码。它在我的环境中运行良好。 并且remove操作不会调用hashCode(),而是调用equals()。 我使用的jdk是1.6.0_23。
答案 1 :(得分:0)
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);
打印
After add.
[Object 1]
After remove
[]
即使我将hashCode更改为
public int hashCode() {
throw new UnsupportedOperationException();
}
它获得相同的结果,因为这些类不使用hashCode()(hashCode()方法除外)
答案 2 :(得分:0)
我找到了问题的原因。
我正在使用Hibernate,它创建了一个自己的org.hibernate.collection.PersistentSet实例,它取代了我的CopyOnWriteArraySet!
.contains()和.remove()不起作用的事实是Hibernate中的一个错误:http://opensource.atlassian.com/projects/hibernate/browse/HHH-3799
我的案例中的解决方案是不重写 .hashCode()方法。
注意:这可能不是所有案例的最佳解决方案。对我来说,它虽然有效。 在上面的链接中,描述了几种解决方法。