2013-08-22 27 views
6

Znalazłem ten komentarz na can StringBuffer objects be keys in TreeSet in Java?Czy potrzebuję metody equals i Hashcode, jeśli moja klasa implementuje porównywalną w Javie?

„Istnieją 2 określa strategie stosowane z Map w Java (bardziej lub mniej)

Hashing. Wejście«Foo»przekształca się w Best-as- możliwa próba wygenerowania liczby, która unikalnie uzyskuje dostęp do indeksu do tablicy (Purists, proszę nie nadużywajcie mnie, celowo upraszczam) .Ten indeks jest tam, gdzie przechowywana jest twoja wartość. Istnieje prawdopodobieństwo, że "Foo" i "Pasek" faktycznie generuje tę samą wartość indeksu, co oznacza, że ​​oba byłyby odwzorowane na tę samą pozycję tablicy Oczywiście to nie może działać, a więc w tym miejscu pojawia się metoda "równa()", która służy do rozróżnienia

Porównanie: Korzystając z metody porównawczej, nie potrzebujesz tego dodatkowego etapu ujednoznacznienia, ponieważ porównanie NIGDY nie powoduje kolizji w pierwszej kolejności. Jedynym kluczem, z którym "Foo" jest równy, jest "Foo". Naprawdę dobrym pomysłem jest jednak, jeśli możesz zdefiniować "equals()" jako compareTo() == 0; dla zachowania spójności. . Nie jest to wymóg”

moje pytanie brzmi następująco: jeśli moja klasa implementuje porównywalne, wtedy to znaczy, że nie trzeba zastąpić równych i metody hashcode za korzystanie z moich przedmiotów jak klucze w zbiorach Hash np

class Person implements Comparable<Person> { 
    int id; 
    String name; 

    public Person(int id, String name) { 
     this.id=id; 
     this.name=name; 
    } 

    public int compareTo(Person other) { 
     return this.id-other.id; 
    } 
} 
.

teraz mogę wykorzystać moje przedmioty osoba w kolekcjach Hashable?

+0

Czy próbowałeś? –

Odpowiedz

6

artykuł, który brough rozmawia TreeSet. zestaw drzewo jest drzewem z każdego węzła ma miejsce określone przez jego wartość w porównaniu do innych wartości już na drzewie.

a hashTable przechowuje pary klucz/wartość w tabeli mieszania. Podczas używania tabeli kontrolnej określasz obiekt, który jest używany jako klucz, oraz wartość, którą chcesz powiązać z tym kluczem. Klucz jest następnie mieszany, a wynikowy kod skrótu jest używany jako indeks, przy którym wartość jest przechowywana w tabeli.

różnica między Hashable i TreeSet że TreeSet nie trzeba hashCode, to po prostu trzeba znać, jeśli potrzebujesz wziąć pozycję w lewo lub prawo w drzewie. do tego możesz użyć Porównaj i nic więcej.

w hashable wystarczy porównać, ponieważ jest inaczej, każdy obiekt dostaje się do jego komórki przez mieszanie, a nie przez porównywanie go z elementami już w kolekcji.

, więc odpowiedź brzmi "nie, można" użyć Person w hashtable tylko z compareTo. u musi zastąpić hashCode() i equals() dla tego

Proponuję także zapoznać this artykuł na hashtables

1

jeśli moja klasa implementuje porównywalne, wtedy to znaczy, że nie trzeba zastąpić równych i metody hashcode za korzystanie z moich przedmiotów jako klucze w kolekcjach Hash. np

Nie, trzeba jeszcze wdrożyć equals() i hashCode(). Metody spełniają bardzo różne funkcje i nie mogą być zastąpione przez compareTo().

  • zwraca wartość logiczną na podstawie równości obiektu. Jest to zwykle równość, a nie równość pola. To może być bardzo różna od pól użytych do porównania obiekt w compareTo(...) chociaż jeśli to ma sens w odniesieniu do podmiotu, sposób equals() może być:

    @Overrides 
    public boolean equals(Object obj) { 
        if (obj == null || obj.getClass() != getClass()) { 
         return false; 
        } else { 
         return compareTo((Person)obj) == 0; 
        } 
    } 
    
  • hashCode() zwraca wartość całkowitą, na przykład, który jest używany w tablice mieszające do obliczenia wiadra, które należy umieścić. Nie ma równoważnego sposobu na uzyskanie tej wartości z compareTo(...).

+0

Prawie wznowiłem twoją odpowiedź, ale jestem z "use" instanceof' dla 'equals' school. –

+0

LOL! Właściwie ja też, ale byłem w trybie prędkości i chciałem, aby kod był ogólny we wszystkich klasach. :-) @ ChrisJester-Young. – Gray

+1

po zwróceniu 'compareTo ((Person) obj)' zwrócisz 'int', ale równa się typ powrotu' boolean', prawda? – eagertoLearn

2

HashTable używa równań i hashCode. Każda klasa ma te metody. Jeśli ich nie wdrożysz, odziedziczysz je.

Niezależnie od tego, czy chcesz je wdrożyć, zależy od tego, czy odziedziczona wersja jest odpowiednia do twoich celów. W szczególności, ponieważ osoba nie ma określonej nadklasy, dziedziczy ona metody Object. Oznacza to, że obiekt Person jest równy samemu sobie.

Potrzebujesz dwóch różnych obiektów Person, które będą traktowane jako równe klawiszom HashTable?

0

TreeSet wymaga porównania, aby dodać wartości do prawej lub lewej strony drzewa. HashMap wymaga metod equals() i Hashcode(), które są dostępne z klasy Object, ale musisz je przesłonić dla swojego celu.

0

Jeśli klasa implementuje Comparable, to sugerowałoby, że instancje klasy reprezentują wartości pewnego rodzaju; ogólnie, gdy klasy zawierają wartości, możliwe będzie istnienie dwóch odrębnych instancji, które utrzymają tę samą wartość i powinny w związku z tym być uznane za równoważne. Ponieważ jedynym sposobem na różnych instancji obiektów należy uznać za równoważny jest dla nich, aby zastąpić equals i hashCode, które mogłyby sugerować, że rzeczy, które wdrażają Comparable powinny przesłonić equals i hashCodechyba że kapsułkowane wartości, na których compare działa będzie unikalny w skali globalnej (co implikuje te odrębne przypadki nigdy nie powinny być uważane za równoważne).

Jako prosty przykład załóżmy, że klasa zawiera pole CreationRank typu long; za każdym razem, gdy tworzone są wystąpienia, ten element jest ustawiony na wartość pobraną z pojedynczego zbioru AtomicLong, a Comparable używa tego pola do szeregowania obiektów w kolejności ich tworzenia. Żadne dwa odrębne wystąpienia klasy nigdy nie będą zgłaszać tego samego CreationRank; w związku z tym jedynym sposobem, w jaki kiedykolwiek powinno być prawdziwe, jest x.equals(y), jeśli x i y odwołują się do tej samej instancji obiektu - dokładnie tak, jak działają domyślne wartości equals i hashCode.

BTW, mający x.compare(y) powrót zero powinno generalnie oznacza, że ​​x.equals(y) zwróci true, i vice versa, ale istnieją pewne przypadki, w których x.equals(y) mogą być fałszywe, ale mimo wszystko powinien x.compare(y) zwracają zero. Może się tak zdarzyć, gdy obiekt zawiera pewne właściwości, które można uszeregować, a inne nie. Weźmy pod uwagę, na przykład, hipoetyczny typ FutureAction, który zawiera enkodowanie DateTime i implementację interfejsu DoSomething.Takie rzeczy mogą być uszeregowane na podstawie zamkniętej daty i godziny, ale może nie istnieć rozsądny sposób rangowania dwóch elementów, które mają tę samą datę i godzinę, ale różne działania. Po tym, jak equals zgłasza fałsz podczas gdy compare zgłasza zero, byłoby bardziej sensowne niż udawanie, że wyraźnie nierównoważne elementy powinny być nazywane "równymi".