2012-01-10 74 views
5

这个问题的答案SO解释我遇到的问题:HashSet.remove() and Iterator.remove() not working解决方法哈希一个HashSet当内部对象改变

基本上,一旦我添加的东西到HashSet的,如果我修改任何字段,那么该集合将会失败任何包含具有完全相同字段的对象的集合的相等性测试,因为它存储在其中的哈希码是用于设置了不同字段的时候。

因此,由于该答案解释了发生了什么,因此,如果具有使用集合的唯一性并且能够修改集合中对象的内部字段,那么这将是一个很好的解决方法吗?或者这是不可能的?

回答

5

从集合中删除要修改的对象,更改它,然后将其添加回来。据我所知,没有标准的Set实现可以处理字段(用于hashCode()compareTo()实现)在存储时被更改。

可选地,如果字段在确定同一性,平等或位置使用(即在hashCode()compareToequals()不使用),那么就没有问题。

+0

选择你的答案,尽管票数,因为它是为AIX基本相同,它来了几秒钟之前:)谢谢。我想我可以在这个实例中使用Set来重新评估。 – AHungerArtist 2012-01-10 15:52:42

7

如果您修改的字段不是平等测试的一部分,则它们也不应该成为哈希码计算的一部分。在这种情况下,没有问题:您可以修改这些字段。

如果字段等于测试的一部分,最简洁的方法可能是从集中删除对象,然后修改并重新插入它。

如果是后者,并且发现自己做了很多事情,那么您可能需要重新访问关于手头问题的数据结构的选择。

3

要解决这个问题,唯一的方法是不要有一个取决于任何可变域的hashCode()方法。如果对象具有独立于其字段值的身份和存在,那么这很容易 - 使用System.identityHashCode()。否则,您可能会将hashCode()基于一个不可变字段。如果没有一个,那么恐怕你运气不好。

1

使用HashMap而不是HashSet。将密钥定义为独特的,不会在时间上发生变化。

-1

使用任何其他集合(也许LinkedList),只有在添加的瞬间检查的独特性,就像在

public class MySetList<E> extends LinkedList<E> implements Set<E> { 
    private static final long serialVersionUID = 1L; 

    @Override 
    public boolean add(E e) { 
     return new HashSet<E>(this).add(e) ? super.add(e) : false; 
    } 
}