Relatie tussen hashCode en is gelijk aan methode in Java

Ik heb op veel plaatsen gelezen dat terwijl het negeren van de equals-methode in Java, de hashCode-methode ook moet worden overschreven, anders is het “het contract schenden”.

Maar tot nu toe heb ik geen enkel probleem ondervonden als ik alleen de methode is gelijk aan, maar niet de hashCode-methode.

Wat is het contract? En waarom heb ik geen probleem als ik het contract schend? In welk geval krijg ik een probleem als ik de hashCode-methode niet heb overschreven?


Antwoord 1, autoriteit 100%

Het probleem dat u zult hebben is met verzamelingen waarbij de uniciteit van elementen wordt berekend volgens zowel .equals()als .hashCode(), bijvoorbeeld sleutels in een HashMap.

Zoals de naam al aangeeft, vertrouwt het op hash-tabellen, en hash-buckets zijn een functie van de .hashCode()van het object.

Als je twee objecten hebt die .equals()zijn, maar verschillende hashcodes hebben, verlies je!

Het deel van het contract dat hier belangrijk is, is: objecten die .equals()zijn MOETEN dezelfde .hashCode()hebben .

Dit is allemaal gedocumenteerd in de javadoc voor Object. En Joshua Blochzegt dat je het moet doen in Effectieve Java. Genoeg gezegd.


Antwoord 2, autoriteit 11%

Volgens het document zal de standaardimplementatie van hashCode een geheel getal retourneren dat voor elk object anders is

Zoveel als redelijk praktisch is, doet de hashCode-methode gedefinieerd door klasse Object dat wel
geef verschillende gehele getallen terug voor verschillende objecten. (Dit wordt meestal geïmplementeerd door:
het interne adres van het object omzetten in een geheel getal, maar deze implementatie
techniek is niet vereist door de programmeertaal JavaTM.)

U wilt echter een tijdje dat de hash-code hetzelfde is voor verschillende objecten met dezelfde betekenis. Bijvoorbeeld

Student s1 = new Student("John", 18);
Student s2 = new Student("John", 18);
s1.hashCode() != s2.hashCode(); // With the default implementation of hashCode

Dit soort problemen zullen optreden als u een hash-gegevensstructuur gebruikt in het verzamelingsframework, zoals HashTable, HashSet. Vooral met verzamelingen zoals HashSet zul je een dubbel element hebben en het Set-contract schenden.


Antwoord 3, autoriteit 7%

Ja, het moet worden overschreven. Als je denkt dat je equals()moet overschrijven, dan moet je hashCode()overschrijven en vice versa. Het algemene contract van hashCode() is:

  1. Telkens wanneer het meer dan eens op hetzelfde object wordt aangeroepen tijdens het uitvoeren van een Java-toepassing, moet de hashCode-methode consequent hetzelfde gehele getal retourneren, op voorwaarde dat er geen informatie wordt gewijzigd die wordt gebruikt in gelijken-vergelijkingen op het object. Dit gehele getal hoeft niet consistent te blijven van de ene uitvoering van een applicatie naar de andere uitvoering van dezelfde applicatie.

  2. Als twee objecten gelijk zijn volgens de equals(Object)-methode, moet het aanroepen van de hashCode-methode op elk van de twee objecten hetzelfde resultaat met een geheel getal opleveren.

  3. Het is niet vereist dat als twee objecten ongelijk zijn volgens de equals(java.lang.Object)-methode, het aanroepen van de hashCode-methode op elk van de twee objecten verschillende integer-resultaten moet opleveren. De programmeur moet zich er echter van bewust zijn dat het produceren van duidelijke integer-resultaten voor ongelijke objecten de prestaties van hash-tabellen kan verbeteren.


Antwoord 4, autoriteit 4%

Het contract is dat als obj1.equals(obj2)dan obj1.hashCode() == obj2.hashCode(), het is vooral om uitvoeringsredenen, zoals Kaarten gebruiken HASHCODE-methode voornamelijk om de vermeldingensleutels te vergelijken.


Antwoord 5, Autoriteit 4%

Bekijk Hashtables, Hashmaps, HashSetsenzovoort. Ze slaan de hashed-sleutel allemaal op als hun sleutels. Bij het aanroepen van get(Object key)De hash van de parameter wordt gegenereerd en opzoeken in de gegeven hashes.

Wanneer u niet overschrijdt hashCode()en het exemplaar van de sleutel is gewijzigd (bijvoorbeeld een eenvoudige string die er helemaal niet toe doet), de hashCode()Kan resulteren in 2 verschillende hashcodes voor hetzelfde object, wat resulteert in het niet vinden van uw opgegeven sleutel in map.get().


Antwoord 6, Autoriteit 3%

Zie Javadoc van java.lang.Object

in hashCode()het zegt:

Als twee objecten gelijk zijn aan de equals(Object)methode,
Vervolgens de hashCodeMethod op elk van de twee objecten must
produceer hetzelfde geheel getal
.

(nadruk door mij).

Als u alleen opheft equals()en niet hashCode()schendt uw klasse deze contract.

Dit wordt ook gezegd in de Javadoc van de equals()methode:

Merk op dat het over het algemeen noodzakelijk is om de hashCode-methode te negeren
Wanneer deze methode wordt overschreven, om de algemene te handhaven
contract voor de hashCodemethode, waarin staat dat gelijke objecten moeten
hebben gelijke hash-codes.


Antwoord 7, Autoriteit 3%

Een contract is: als twee objecten gelijk zijn, moeten ze dezelfde hashcode hebben en als twee objecten niet gelijk zijn, kunnen ze al dan niet dezelfde hash-code hebben.

Probeer uw object te gebruiken als sleutel in Hashmap (bewerkt na reactie van Joachim-Sauer), en u zult beginnen met problemen. Een contract is een richtlijn, niet iets dat op u wordt gedwongen.

Other episodes