这个bug我花了一段时间才发现...

考虑这个方法:

public void foo(Set<Object> set)
{
    Object obj=set.iterator().next();
    set.remove(obj)
}

我使用非空哈希集调用该方法,但不会删除任何元素!

为什么会这样呢?

有帮助吗?

解决方案

有关一个HashSet,这可以,如果对象的hashCode改变它已被添加到该组之后。所述HashSet.remove()方法然后可以看在错误的哈希桶和未能找到它。

此,如果你没有iterator.remove()可能不会发生,但在任何情况下,在一个HashSet其的hashCode可以改变存储的对象是一个等待发生的事故(如你发现)。

其他提示

益智?如果Object.hashCodeObject.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中很多经验了,所以我可能是完全错误的。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top