有人可以向我解释为什么以下不起作用(跑道是Hibernate PersistentSet)?
System.out.println("size before " + runways.size());
Iterator<Runway> deleteIterator = runways.iterator();
while (deleteIterator.hasNext()) {
Runway rwy = deleteIterator.next();
if (rwy == rwy3) {
System.out.println("remove !");
deleteIterator.remove();
}
}
System.out.println("size after " + runways.size());
我得到了系统。输出日志:
INFO: size before 3
INFO: remove !
INFO: size after 3
我认为通过迭代器进行删除是安全可行的。 你看到日志“删除”!表示调用remove()方法。
编辑:PersistentSet在Iterator接口上的remove方法有问题。
答案 0 :(得分:3)
检查以确保hashCode()
对象上的equals()
和Runway
方法被覆盖并正确无误。
答案 1 :(得分:3)
//编辑:仅供参考此代码是代码失败的示例。正确覆盖您的equals()
和hashCode()
。
要跟进JustinKSU的观点,如果你没有很好地实施hashCode()
和equals()
,那么你所做的就行不通了。如果我弄乱了equals()
和hashCode()
。
public static void main(String[] args) {
Set<Runway> runways = new HashSet<Runway>();
Runway rwy1 = new Runway();
Runway rwy2 = new Runway();
Runway rwy3 = new Runway();
runways.add(rwy1);
runways.add(rwy2);
runways.add(rwy3);
System.out.println("size before " + runways.size());
Iterator<Runway> deleteIterator = runways.iterator();
while (deleteIterator.hasNext()) {
Runway rwy = deleteIterator.next();
if (rwy == rwy3) {
System.out.println("remove !");
deleteIterator.remove();
}
}
System.out.println("size after " + runways.size());
}
private static class Runway {
@Override
public boolean equals(Object obj) {
return false;
}
@Override
public int hashCode() {
return (new Random()).nextInt();
}
}
答案 2 :(得分:0)
从查看JDK源代码(我发现它here),HashSet
返回的迭代器使用HashSet
的内部删除方法之一来执行实际的删除
要使HashSet
正常工作,您需要将equals
和hashCode
单独留在Runway
课程中,或同时覆盖它们。这个SO问题讨论了这个问题:What issues should be considered when overriding equals and hashCode in Java?
答案 3 :(得分:0)
我的equals和hashCode方法是由Eclipse自己创建的。所以它不是来自他们。
但是在我的问题开始时我太快了。我忘了Runways是来自Hibernate的PersistentSet(而不是java.util.HashSet)
我发现这个bug解释了为什么不能从PersistenSet迭代器中删除对象的原因。
这个bug看起来很古老而且很复杂。 我唯一的选择是从第一个重新创建一个集合,没有我不想要的元素。