2012-01-10 72 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; 
    } 
}