2014-11-08 12 views
5

Bardzo ostatni akapit pkt 9 z Effective Java, 2-gie wydanie, J. Bloch mówi, że dla klas wartości jak Integer, String, Date itp przekazujących funkcję dokładnej wartości, które klasa jako the hashCode nie jest dobrym pomysłem.Dlaczego wartość klasy wartości jest jego hashCode "nie jest dobrym pomysłem"?

Tak więc klasa Integer zwracająca value liczby całkowitej, którą reprezentuje jako hashCode, nie jest tak dobra.

Nie jest również hashCode() z String zwracająca wartość całkowitą bezpośrednio odwzorowaną z ogólnej treści, tj. Znaków, które ma instancja String.

Te hashCode() - są wyraźnie zgodne z umową.

Dla mnie wygląda na to, że jest to dobry pomysł, a nie zły - hashCode - różnią się w zależności od wartości różnych obiektów, a te hashCodes są "znormalizowane", zanim zostaną rozłożone na wiadra HashMap/HashSet - tak że hashCode -s z wpisami nie tworzą nastawienie na którym wiadro wpis trafi w

Co ja tu brakuje. - Co sprawia, że ​​mapowanie wartości klasy bezpośrednio do hashCode „zły pomysł"?

TIA

// ===========================

EDIT zobaczyć

pls także komentarze w odpowiedzi na pytanie Steve'a Sieberta.

Odpowiedz

4

Co ona mówi, że ci, specyfikacja javadoc powiedzieć dokładnie, jak hashCode jest tworzony. Dzięki temu aplikacje mogą teraz polegać na tym, że to zawsze musi być prawdziwe ... a teraz te implementacje nigdy nie mogą zmienić sposobu generowania kodu haszującego.

To nie znaczy, że nie powinieneś czerpać haszu ze swoich wartości ...tylko nie mów ludziom, jak to zrobić w specyfikacji =)

+0

zgadzam się z tym. ale rozwiązanie tego problemu powinno wymusić zasadę, że "hashCode" nie może być używany jako wskaźnik/funkcjonalny substytut "wartości", a raczej niż wchodzenie pomiędzy tą miłą relację między 'wartością' i' hashCode() 'i tym samym pomiędzy' equals() 'i' hashCode() '. – Roam

+0

Całkowicie się z tobą zgadzam, a hashCode może być w praktyce traktowany jako taki, który zwraca "mniej inteligentny/stratny" obraz rzeczywistej wartości obiektu - podatny na paradoks urodzin. Ale tak naprawdę hash nie jest konieczny * trzeba * mieć relacjęscript z wartością ... hashCode musi zawsze zwracać tę samą wartość int dla tego samego obiektu (jednak jest to zdefiniowane przez ciebie), więc obiekt można znaleźć w oczekiwane wiadro. Zwykle odbywa się to poprzez mieszanie jednej/więcej wartości obiektu ... co ma sens. Ale jeśli można to zrobić, powiedzmy ... magii ... to kim ja jestem, by sądzić? =) –

+0

przywiązanie 'hashCode' do' wartości' zapewniłoby, że "jeśli dwa obiekty nie są równe, to żaden z nich nie jest ich hashCodes" i jest to dobre rozwiązanie dla równomiernie rozmieszczonych wpisów w mieszających się mieszających tablicach - chociaż nie jest to wymóg określony w umowie. Nie widziałem ani nie mogę wymyślić lepszego sposobu na zrobienie tego. – Roam

-1

Interfejs API języka Java właśnie to robi, zwraca liczbę całkowitą.

Integer t = ...; 
t.intValue() == t.hashCode(); // true 

Mam tę samą książkę w pracy. Popatrzę na to w poniedziałek.

Jeśli jesteś naprawdę martwi, wdrożenie FNV-1a hash:

int hash = 0x4C1DF00D; 
    hash = (hash^value) * 0x01000193; 
+0

Zastanawiam się, dlaczego w dół? Planowałem dojść do tego samego wniosku co @SotiriosDelimanolis, ale mam książkę gdzie indziej i nie wiedziałem, że jest ona dostępna za darmo w Internecie. –

3

full quote jest

Wiele klas w bibliotekach platformy Java, takie jak String, Integer i Date, zawierają w swoim podaje dokładną wartość zwróconą przez ich metodę hashCode w zależności od wartości instancji. Zwykle nie jest to dobry pomysł, ponieważ poważnie ogranicza on twoje możliwości: w celu poprawy funkcji skrótu w przyszłych wersjach. Jeśli nie zostanie podana szczegółowa funkcja skrótu, która nie zostanie określona, ​​a wykryta zostanie usterka lub zostanie znaleziona lepsza funkcja skrótu , można zmienić funkcję mieszania w następnej wersji , mając pewność, że żaden klient nie będzie zależał od dokładnych wartości zwracanych przez skrót. funkcjonować.

Podkreślam moją. Książka właśnie stwierdza, że ​​ogólnie uważa się za złą praktykę ujawnienie szczegółów implementacji w specyfikacji. To sprawia, że ​​jest odporny na zmiany.

Fakt, że został wprowadzony jako zwracający dokładną wartość (dla Integer) lub pewną wyliczoną wartość (dla Date i String) nie jest zły.

Powiązane problemy