为什么不从套装中删除?

时间:2009-07-06 11:53:33

标签: java puzzle

这个错误花了我一段时间才找到......

考虑这种方法:

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

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

为什么会这样?

6 个答案:

答案 0 :(得分:7)

对于HashSet,如果对象的hashCode在添加到集合后发生更改,则会发生这种情况。然后,HashSet.remove()方法可能会查找错误的Hash存储桶而无法找到它。

如果你执行了iterator.remove(),这可能不会发生,但无论如何,将对象存储在hashCode可以更改的HashSet中是一件等待发生的事故(正如你所发现的那样)。

答案 1 :(得分:3)

益智?如果Object.hashCodeObject.equals或“哈希集”未正确实施(例如,请参阅java.net.URL - 请使用URI)。

此外,如果集合(直接或间接)包含自身,可能会发生奇怪的事情(确切地说,月亮的实现和阶段依赖于什么)。

答案 2 :(得分:2)

集合的实现类型和集合中的对象是什么?

  • 如果它是HashSet,请确保对象的hashCode()方法的值在set.put(...)set.remove(...)之间保持不变。
  • 如果是TreeSet,请确保不会对影响集合的比较器或对象的compareTo方法的对象进行修改。

在这两种情况下,set.put(...)set.remove(...)之间的代码违反了相应类实现定义的协定。根据经验,最好将不可变对象用作设置内容(以及Map键)。就其性质而言,这些对象在存储在集合中时无法更改。

如果您正在使用其他一些set实现,请查看其JavaDoc的合同;但是,当对象包含在集合中时,equalshashCode通常必须保持不变。

答案 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()

     

迭代器的行为是   未指定,如果底层   集合被修改而   迭代正在以任何方式进行   除了通过调用此方法。

Reference

答案 5 :(得分:-3)

我不禁感到(部分)问题是该集合是按值传递的,而不是参考。我在Java方面没有太多经验,所以我可能完全错了。