题
这个bug我花了一段时间才发现...
考虑这个方法:
public void foo(Set<Object> set)
{
Object obj=set.iterator().next();
set.remove(obj)
}
我使用非空哈希集调用该方法,但不会删除任何元素!
为什么会这样呢?
解决方案
有关一个HashSet,这可以,如果对象的hashCode改变它已被添加到该组之后。所述HashSet.remove()方法然后可以看在错误的哈希桶和未能找到它。
此,如果你没有iterator.remove()可能不会发生,但在任何情况下,在一个HashSet其的hashCode可以改变存储的对象是一个等待发生的事故(如你发现)。
其他提示
益智?如果Object.hashCode
,Object.equals
或 “散列集” 被错误地实现(参见例如,java.net.URL
- 使用URI
)。
此外,如果所述一组(直接或间接)包含本身,一些奇怪很可能发生(什么是月亮依赖性的执行和相)。
该集合的实现类型是什么以及该集合内有哪些对象?
- 如果是 HashSet,请确保该对象的 hashCode() 方法的值在
set.put(...)
和set.remove(...)
. - 如果它是 TreeSet,请确保对对象进行的修改不会影响集合的比较器或对象的
compareTo
方法。
在这两种情况下,之间的代码 set.put(...)
和 set.remove(...)
违反了相应类实现定义的契约。根据经验,使用不可变对象作为设置内容(以及 Map 键)是一个好主意。就其本质而言,这些对象在存储在集合中时无法更改。
如果您使用其他集合实现,请查看其 JavaDoc 以了解其契约;但通常要么 equals
或者 hashCode
当对象包含在集合中时必须保持不变。
除了缺少 ';' 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();
}
它应该是:
public void foo(Set<Object> set)
{
Iterator i = set.iterator();
i.next();
i.remove();
}
该错误可能是事做:
公开无效删除()强>
迭代器的行为是 如果未指定底层 集合而修改 迭代过程中以任何方式 不是通过调用此方法等。
(参考)
我不禁觉得(的部分)的问题是,设定通过值传递,不能引用。我没有在Java中很多经验了,所以我可能是完全错误的。