Nadpisywanie metody hashCode() jest ściśle związane z nadpisywaniem equals(): obie metody stanowią podstawę poprawnego użycia obiektu w kolekcjach typu HashMap, HashSet, Hashtable i innych strukturach opartych na porównaniach i funkcjach haszujących.
Zasady:
equals(), koniecznie nadpisz także hashCode().equals() powinny zwracać ten sam hashCode().Objects.hash() lub szablonów IDE, aby uniknąć błędów.hashCode() powinien zwracać tę samą wartość dla tego samego obiektu przez cały czas jego "życia" (jeśli pola brane pod uwagę w hashCode pozostają niezmienne).class User { private String name; public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof User)) return false; User user = (User) o; return Objects.equals(name, user.name); } public int hashCode() { return Objects.hash(name); } }
Pytanie: "Co się stanie, jeśli dwa różne obiekty według equals() zwrócą ten sam hashCode()? Czy będzie to błąd?"
Odpowiedź: Nie, to nie jest błąd. Kolizje kodów haszujących są dozwolone i oczekiwane — ważne jest tylko, aby jeśli obiekty są równe według equals, ich hashCode był taki sam. Jeśli różne obiekty w equals zwracają ten sam hashCode, kolekcje będą działały wolniej (z powodu większej liczby kolizji), ale wciąż poprawnie.
Historia
W oprogramowaniu finansowym porównywano projekty według kilku pól, ale nadpisano tylko equals(). Przechowywano obiekty w HashSet, występowały duplikaty, ponieważ hashCode() nie został nadpisany i działał domyślnie (różnił się dla każdego egzemplarza).
Historia
W systemie zarządzania magazynem po dodaniu zmian w logice biznesowej rozszerzono equals(), ale zapomniano zaktualizować hashCode(). Obiekty z różnymi hashCode, ale equals=true, ginęły w HashMap (nie można ich było znaleźć według klucza), co prowadziło do dużych błędów finansowych.
Historia
W aplikacji webowej używano zmiennych pól do obliczania hashCode. Po aktualizacji wartości wewnętrznego pola hash się zmieniał, a obiekt "gubił się" w HashSet/HashMap: nie można go było znaleźć ani usunąć za pomocą standardowych metod, co prowadziło do wycieków pamięci i bugów.