这个错误花了我一段时间才找到......
考虑这种方法:
public void foo(Set<Object> set)
{
Object obj=set.iterator().next();
set.remove(obj)
}
我使用非空哈希集调用该方法,但不会删除任何元素!
为什么会这样?
答案 0 :(得分:7)
对于HashSet,如果对象的hashCode在添加到集合后发生更改,则会发生这种情况。然后,HashSet.remove()方法可能会查找错误的Hash存储桶而无法找到它。
如果你执行了iterator.remove(),这可能不会发生,但无论如何,将对象存储在hashCode可以更改的HashSet中是一件等待发生的事故(正如你所发现的那样)。
答案 1 :(得分:3)
益智?如果Object.hashCode
,Object.equals
或“哈希集”未正确实施(例如,请参阅java.net.URL
- 请使用URI
)。
此外,如果集合(直接或间接)包含自身,可能会发生奇怪的事情(确切地说,月亮的实现和阶段依赖于什么)。
答案 2 :(得分:2)
集合的实现类型和集合中的对象是什么?
set.put(...)
和set.remove(...)
之间保持不变。compareTo
方法的对象进行修改。在这两种情况下,set.put(...)
和set.remove(...)
之间的代码违反了相应类实现定义的协定。根据经验,最好将不可变对象用作设置内容(以及Map键)。就其性质而言,这些对象在存储在集合中时无法更改。
如果您正在使用其他一些set实现,请查看其JavaDoc的合同;但是,当对象包含在集合中时,equals
或hashCode
通常必须保持不变。
答案 3 :(得分:1)
超越失踪';'在set.remove(obj)
之后,它可能发生在三种情况下(引自javadoc)。
ClassCastException - if the type of the specified element is incompatible with this set (optional). NullPointerException - if the specified element is null and this set does not support null elements (optional). UnsupportedOperationException - if the remove method is not supported by this set.
您也可以尝试:
public void foo(Set<Object> set)
{
Object obj=set.iterator().next();
iterator.remove();
}
答案 4 :(得分:1)
应该是:
public void foo(Set<Object> set)
{
Iterator i = set.iterator();
i.next();
i.remove();
}
该错误可能与某些事情有关:
public void remove()
迭代器的行为是 未指定,如果底层 集合被修改而 迭代正在以任何方式进行 除了通过调用此方法。
答案 5 :(得分:-3)
我不禁感到(部分)问题是该集合是按值传递的,而不是参考。我在Java方面没有太多经验,所以我可能完全错了。