2009-10-04 6 views
5

Czy dane wyjściowe z Object.hashCode() muszą być takie same we wszystkich implementacjach JVM dla tego samego obiektu?Java, Object.hashCode() stała wyniku we wszystkich JVMs/Systems?

Na przykład, jeśli "test".hashCode() zwraca 1 na 1.4, może potencjalnie zwrócić 2 z 1.6. A co, jeśli systemy operacyjne były inne lub inna była architektura procesorów między instancjami?

Odpowiedz

14

Nie. Wyjście z hashCode może zmieniać między implementacjami JVM, a nawet między różnymi wykonaniami programu na tym samym JVM.

Jednak w konkretnym przykładzie dałeś wartość "test".hashCode()będzie faktycznie być spójne, ponieważ realizacja hashCode dla String obiektów jest częścią API String (patrz the Javadocs for java.lang.String i this other SO post).

+0

(Chociaż będzie inaczej, jeśli uda Ci się znaleźć 1.0 JDK. Zepsuta definicja w dokumentach API faktycznie wyrzuciłaby wyjątki, jeśli zostanie zaimplementowana.) –

+0

Jest również dobrze zdefiniowany dla większości kolekcji – finnw

5

Od API

umowy generalnej z hashcode jest:

  • Ilekroć jest wywoływane na tym samym obiekcie więcej niż jeden raz w trakcie wykonywania aplikacji Java, metoda hashCode musi konsekwentnie zwracają ta sama liczba całkowita, pod warunkiem, że nie są modyfikowane żadne informacje używane w porównaniu do obiektu. Ta liczba całkowita nie musi pozostawać spójna od jednego wykonania aplikacji do innego wykonania tej samej aplikacji.
  • Jeśli dwa obiekty są równe zgodnie z metodą equals (Object), wówczas wywołanie metody hashCode na każdym z dwóch obiektów musi dać taki sam wynik całkowity.
  • Nie jest wymagane, że jeśli dwa obiekty są nierówne zgodnie z metodą equals (java.lang.Object), wywołanie metody hashCode na każdym z dwóch obiektów musi dawać różne wyniki liczb całkowitych. Jednak programista powinien mieć świadomość, że generowanie różnych wyników całkowitych dla nierównych obiektów może poprawić wydajność tablic asocjacyjnych.

W miarę możliwości metoda hashCode zdefiniowana przez obiekt klasy zwraca różne liczby całkowite dla różnych obiektów. (Jest to zwykle realizowane poprzez przekształcenie wewnętrzny adres obiektu do liczby całkowitej, ale technika ta realizacja nie jest wymagane przez język programowania JavaTM.)

+0

+ 1 do cytowania właściwej części api. –

+2

-1 to nie odpowiada na pytanie – finnw

+5

@finnw: Tak, robi; hashCode nie musi zwracać tej samej wartości dla różnych * wersji * tej samej wersji w tym samym systemie dla tej samej aplikacji, nieważne w różnych wersjach lub różnych systemach lub różnych aplikacjach. –

2

No, wynik hashCode() jest tylko stała podczas pojedynczego wykonania . Nie należy oczekiwać, że wynik funkcji będzie taki sam między wykonaniami, nie mówiąc już o wersjach i platformach JRE.

0

Po pierwsze, wynik hashCode zależy w dużej mierze od typu obiektu i jego implementacji. każda klasa, w tym jej podklasy, może definiować własne zachowanie. możesz polegać na nim zgodnie z generalną umową opisaną w javadoc, jak również w innych odpowiedziach. ale wartość nie jest wymagana, aby pozostać taka sama po ponownym uruchomieniu maszyny wirtualnej. zwłaszcza jeśli zależy to od implementacji .hashCode klas stron trzecich.

odwołując się do konkretnej implementacji klasy String, nie powinieneś polegać na wartości zwracanej. jeśli program zostanie wykonany na innej maszynie wirtualnej, może potencjalnie ulec zmianie.

jeśli odnosisz się wyłącznie do Słońca Vm, można argumentować, że Sun nie złamie - nawet źle zaprogramowanego - istniejącego kodu., więc "test" .hashCode() zawsze zwróci dokładnie 3556498 dla dowolnej wersji Sun VM.

jeśli chcesz umyślnie strzelać sobie w stopę, idź dalej i polegaj na tym. ludzie, którzy będą musieli naprawić kod na "Maszynie do 2015 Nintendo Java VM for Hairdryer", będą w nocy wykrzykiwać twoje imię.

0

Jak już wspomniano, dla wielu implementacji domyślnym zachowaniem hashCode() jest zwracanie adresu obiektu. Oczywiście może się to różnić za każdym razem, gdy program jest uruchamiany. Jest to również zgodne z domyślnym zachowaniem equals(): dwa obiekty są równe tylko wtedy, gdy są tym samym obiektem (gdzie x i y mają wartość inną niż null, x.equals (y) wtedy i tylko wtedy, gdy x == y) .

Dla każdej klasy, w której hashCode() i equals() są nadpisane, generalnie są obliczane w sposób deterministyczny w oparciu o wartości niektórych lub wszystkich członków. Tak więc w praktyce jest prawdopodobne, że jeśli obiekt w jednym przebiegu programu można powiedzieć, że jest równy obiektowi w innym przebiegu programu, a kod źródłowy jest taki sam (w tym takie rzeczy jak kod źródłowy dla Stringa .hashCode(), jeśli jest wywoływana przez nadpisanie hashCode(), kody skrótu będą takie same.

Nie jest to gwarantowane, chociaż trudno jest myśleć o rozsądnym, realnym przykładzie.

+0

@ Mark: rozsądnym przykładem jest tu, gdzie nadpisujesz ' hashCode() 'i mają hashcode calc zawierają kod skrótu obiektu komponentu, którego' hashCode() 'nie jest nadpisany. –

+0

To by to zrobiło, ale wtedy nie byłbyś w stanie pozwolić na równe dwa obiekty. Dwa "równe" obiekty miałyby różne hashkody. Jeśli umieścisz taki obiekt w HashMapie, nie będziesz mógł go znaleźć ponownie. –

0

Jedyna prawda: hashcode jest taki sam dla uruchomienia aplikacji. Kolejne uruchomienie może dać inne hashcode.

Gdy pytasz o kod skrótu obiektu, JVM tworzy go za pomocą jednego z algorytmów RNG i umieszcza go w nagłówku obiektu do przyszłego wykorzystania. Wystarczy spojrzeć na funkcję get_next_hash w OpenJDK.

Algorytm RNG jest konfigurowany z JVM Arg -XX: hashCode = X, gdzie x jest cyfrą:

0 - Park Miller RNG (domyślnie)

1 - F (adres globalny)

2 - stała 1

3 - sekwencyjny licznik

4 - adres obiektu w sterty

5 - Xorshift (najszybciej)

Gdy hashcode równa adres w sterty - jest czasem niewygodne, ponieważ GC może poruszać przedmioty do innej komórki sterty itp

Powiązane problemy