hashCode z Objecta nie jest adresem w pamięci, może być co najwyżej na jego podstawie obliczony. Przede wszystkim obiektów danego typu może być więcej niż możliwych hashCode'ów, więc poleganie na unikalności hashCode'a jest naiwne i błędne.
identityHashCode czyli hashCode z Objecta jest używany rzadko, bo przy nadpisywaniu equalsa musisz nadpisać hashCode'a. Jeśli dwa obiekty są równe (tzn equals zwraca true
) to muszą mieć taki sam hashCode. Stały hashCode, np hashCode zawsze równy 1 spełnia kontrakt equals/hashCode dla każdego equalsa.
Używanie standardowego hashCode z Objecta jest nie tylko błędne w większości przypadków, ale także ma negatywny wpływ na wydajność. Oryginalny hashCode z Objecta jest liczony na podstawie adresu obiektu, ale obiekty podczas GC (garbage collection) zmieniają swój adres. Z tego wynika, że jeśli identity hash code było policzone na obiekcie, to GC musi tego hashCode'a gdzieś zapisać podczas kompaktowania sterty. Zamiast dokładać nowe pole do każdego Objecta JVM ma osobną mapę z zapisanymi hashCode'ami. Więcej szczegółów np tutaj: https://stackoverflow.com/q/3796699 Zapisywanie hashCode'a musi być ponieważ identitty hashCode dla tego samego obiektu nie może się zmieniać.
Polecam wyguglować frazę: "equals hashcode contract".