2012-01-10 12 views
5

Odpowiedź na to SO wyjaśnia problem mam: HashSet.remove() and Iterator.remove() not workingObejście dla hash dla HashSet gdy obiekt wewnętrzny zmienia

Zasadniczo raz dodam coś do HashSet, jeśli zmiany któregokolwiek z jej pól, wtedy zestaw nie przejdzie pomyślnie testów równości ze zbiorem zawierającym obiekt z dokładnie tymi samymi polami, ponieważ kod skrótu, w którym był przechowywany, był przeznaczony na czas ustawiania różnych pól.

Tak więc, ponieważ odpowiedź wyjaśnia, co się dzieje, jakie byłoby dobre obejście tego, aby mieć zarówno wyjątkowość używania zestawu, jak i móc modyfikować wewnętrzne pola obiektów w zestawie? Czy to po prostu niemożliwe?

Odpowiedz

5

Usuń z zestawu obiekt, który chcesz zmodyfikować, zmień go, a następnie dodaj z powrotem. O ile mi wiadomo, nie ma standardowej implementacji Set, która poradzi sobie z polami (które są używane w implementacji hashCode() lub compareTo()), które zostały zmienione podczas przechowywania.

Alternatywnie, jeśli nie pola są wykorzystywane do określania tożsamości, równe lub położenia (to znaczy nie są wykorzystywane w hashCode(), compareTo lub equals()), to nie ma żadnego problemu.

+0

Wybór odpowiedź mimo liczby głosów, ponieważ jest zasadniczo taka sama jak AIX i przyszedł kilka sekund wcześniej :) Dzięki. Myślę, że mógłbym dokonać ponownej oceny przy użyciu zestawu w tym przypadku. – AHungerArtist

7

Jeśli zmienione pola nie są częścią testu równości, nie powinny być częścią obliczania kodu skrótu. W takim przypadku nie ma problemu: możesz po prostu zmodyfikować te pola.

Jeśli pole jest częścią testu równości, najpewniej najczystszym sposobem jest usunięcie obiektu z zestawu, a następnie zmodyfikowanie go i ponowne włożenie.

Jeśli to ostatnie, a znajdziesz się robić to dużo, może chcesz ponownie odwiedzić Wybór struktury danych na problem pod ręką.

3

Jedynym sposobem, aby obejść to byłoby nie mieć hashCode() metodę, która zależy od wszelkich polach modyfikowalnych. Jeśli obiekty mają tożsamość i istnienie, które są niezależne od wartości ich pól, to jest to łatwe - użyj System.identityHashCode(). W przeciwnym razie możesz bazować na hashCode() na jednym niezmiennym polu. Jeśli go nie ma, obawiam się, że nie masz szczęścia.

1

Użyj HashMap zamiast HashSet. Zdefiniuj klucz jako coś wyjątkowego, co nie zmieni się w czasie.

-1

pomocą żadnej innej kolekcji (może LinkedList) i sprawdzić unikalność tylko w momencie dodawania, jak w

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; 
    } 
} 
Powiązane problemy