Programmering

Sammenligning av Java-objekter med lik () og hashcode ()

I dette Java Challenger du lærer hvordan er lik() og hashcode () kombinere for å gjøre objektsammenligning effektiv og enkel i Java-programmene dine. Enkelt sagt, disse metodene fungerer sammen for å verifisere om to objekter har de samme verdiene.

Uten er lik() og hashcode () vi måtte lage veldig store "hvis"sammenligninger, sammenligning av hvert felt fra et objekt. Dette vil gjøre koden veldig forvirrende og vanskelig å lese. Sammen hjelper disse to metodene oss med å skape mer fleksibel og sammenhengende kode.

Få Java Challengers kildekode.

Overstyring er lik () og hashcode () i Java

Overstyring av metoden er en teknikk der oppførselen til foreldreklassen eller grensesnittet blir skrevet igjen (overstyrt) i underklassen for å dra nytte av polymorfisme. Hver Gjenstand i Java inkluderer en er lik() og en hashcode () metoden, men de må overstyres for å fungere skikkelig.

Å forstå hvordan overordnet fungerer med er lik() oghashcode (), kan vi studere implementeringen av dem i de viktigste Java-klassene. Nedenfor er er lik() metoden i Gjenstand klasse. Metoden sjekker om den nåværende forekomsten er den samme som den tidligere passerte Gjenstand.

 offentlig boolsk er lik (Objekt obj) {retur (dette == obj); } 

Når hashcode () metoden overstyres ikke, standardmetoden i Gjenstand klasse vil bli påkalt. Dette er en innfødt metode, som betyr at den vil bli utført på et annet språk som C, og vil returnere noe kode angående objektets minneadresse. (Det er ikke så viktig å vite nøyaktig hvordan denne metoden fungerer med mindre du skriver JDK-kode.)

 @HotSpotIntrinsicCandidate offentlig innfødt int hashCode (); 

Når er lik() og hashcode () metoder overstyres ikke, vil du se de ovennevnte metodene påkalt i stedet. I dette tilfellet oppfyller ikke metodene det virkelige formålet med er lik() og hashcode (), som er å sjekke om to eller flere objekter har de samme verdiene.

Som regel når du overstyrer er lik() du må også overstyre hashcode ().

Sammenligne objekter med lik ()

Vi bruker er lik() metode for å sammenligne objekter i Java. For å avgjøre om to objekter er like, er lik() sammenligner verdiene til objektenes attributter:

 public class EqualsAndHashCodeExample {public static void main (String ... equalsExplanation) {System.out.println (new Simpson ("Homer", 35, 120) .equals (new Simpson ("Homer", 35,120))); System.out.println (nye Simpson ("Bart", 10, 120). Like (nye Simpson ("El Barto", 10, 45))); System.out.println (nye Simpson ("Lisa", 54, 60) .ekvivalenter (nytt objekt ())); } statisk klasse Simpson {privat strengnavn; privat alder; privat int vekt; offentlig Simpson (strengnavn, int alder, int vekt) {this.name = navn; this.age = alder; denne. vekt = vekt; } @ Override offentlig boolsk er lik (Objekt o) {hvis (dette == o) {returner sant; } hvis (o == null || getClass ()! = o.getClass ()) {return false; } Simpson simpson = (Simpson) o; retur alder == simpson.age && vekt == simpson.vekt && name.equals (simpson.name); }}} 

I den første sammenligningen, er lik() sammenligner gjeldende objektforekomst med objektet som er sendt. Hvis de to objektene har de samme verdiene, er lik() vil returnere ekte.

I den andre sammenligningen, er lik()sjekker for å se om det passerte objektet er null, eller hvis den er skrevet som en annen klasse. Hvis det er en annen klasse, er ikke objektene like.

Endelig, er lik() sammenligner objektenes felt. Hvis to objekter har de samme feltverdiene, er objektene de samme.

Analysere objektsammenligninger

La oss nå se resultatene av disse sammenligningene i vår hoved() metode. Først sammenligner vi to Simpson gjenstander:

 System.out.println (nye Simpson ("Homer", 35, 120). Like (nye Simpson ("Homer", 35, 120))); 

Objektene her er identiske, så resultatet blir ekte.

Deretter sammenligner vi to Simpson gjenstander igjen:

 System.out.println (ny Simpson("Bart", 10, 45). Likestillinger (ny Simpson("El Barto", 10, 45))); 

Objektene her er nesten identiske, men navnene deres er forskjellige: Bart og El Barto. Derfor blir resultatet falsk.

Til slutt, la oss sammenligne en Simpson objekt og en forekomst av klassen Objekt:

 System.out.println (ny Simpson("Lisa", 54, 60). Like (ny Gjenstand())); 

I dette tilfellet blir resultatet falsk fordi klassetypene er forskjellige.

er lik () versus ==

Ved første øyekast, den == operatør og er lik() metoden kan se ut til å gjøre det samme, men i sannhet fungerer de annerledes. De == operatøren sammenligner om to objektreferanser peker på det samme objektet. For eksempel:

 System.out.println (homer == homer2); 

I den første sammenligningen instanserte vi to forskjellige Simpson tilfeller som bruker ny operatør. På grunn av dette, variablene homer og homer2 vil peke på annerledes Gjenstand referanser i hukommelsesbunken. Så det får vi falsk som resultatet.

System.out.println (homer.equals (homer2)); 

I den andre sammenligningen overstyrer vi er lik() metode. I dette tilfellet vil bare navnene bli sammenlignet. Fordi navnet på begge Simpson gjenstander er “Homer” vil resultatet bli ekte.

Unikt å identifisere objekter med hashcode ()

Vi bruker hashcode () metode for å optimalisere ytelsen når du sammenligner objekter. Utførerhashcode () returnerer en unik ID for hvert objekt i programmet ditt, noe som gjør oppgaven med å sammenligne hele tilstanden til objektet mye enklere.

Hvis et objekts hashkode ikke er det samme som et annet objekts hashkode, er det ingen grunn til å utføre er lik() metode: du vet bare at de to objektene ikke er de samme. På den annen side, hvis hashkoden er det samme, så må du utføre er lik() metode for å bestemme om verdiene og feltene er de samme.

Her er et praktisk eksempel med hashcode ().

 offentlig klasse HashcodeConcept {public static void main (String ... hashcodeExample) {Simpson homer = new Simpson (1, "Homer"); Simpson bart = nye Simpson (2, "Homer"); boolsk isHashcodeEquals = homer.hashCode () == bart.hashCode (); if (isHashcodeEquals) {System.out.println ("Skal sammenlignes med lik metode også."); } annet {System.out.println ("Bør ikke sammenlignes med lik metode fordi" + "id er forskjellig, det betyr at objektene ikke er like helt sikkert."); }} statisk klasse Simpson {int id; Strengnavn; offentlig Simpson (int id, strengnavn) {this.id = id; this.name = navn; } @ Overstyr offentlig boolsk er lik (Objekt o) hvis (dette == o) returnerer sant; hvis (o == null @ Override public int hashCode () {return id;}}} 

EN hashcode () som alltid returnerer den samme verdien er gyldig, men ikke veldig effektiv. I dette tilfellet vil sammenligningen alltid komme tilbake ekte, så er lik() metoden vil alltid bli utført. Det er ingen ytelsesforbedring i dette tilfellet.

Bruke lik () og hashcode () med samlinger

De Sett grensesnittet er ansvarlig for at ingen dupliserte elementer blir satt inn i en Sett underklasse. Følgende er noen av klassene som implementerer Sett grensesnitt:

  • HashSet
  • TreeSet
  • LinkedHashSet
  • CopyOnWriteArraySet

Bare unike elementer kan settes inn i en Sett, så hvis du vil legge til et element i HashSet klasse (for eksempel), må du først bruke er lik() og hashcode () metoder for å verifisere at elementet er unikt. Hvis den er lik() og hashcode ()metodene ikke ble overstyrt i dette tilfellet, risikerer du å sette inn dupliserte elementer i koden.

I koden nedenfor bruker vi legge til metode for å legge til et nytt element i en HashSet gjenstand. Før det nye elementet er lagt til, HashSet sjekker for å se om elementet allerede eksisterer i den gitte samlingen:

 hvis (e.hash == hash && ((k = e.key) == key || (key! = null && key.equals (k)))) break; p = e; 

Hvis objektet er det samme, blir ikke det nye elementet satt inn.

Hash-samlinger

Sett er ikke den eneste samlingen som bruker er lik() og hashcode (). HashMap, Hashtable og LinkedHashMap krever også disse metodene. Hvis du ser en samling som har prefikset "Hash", kan du som regel være sikker på at den krever å overstyre hashcode () og er lik() metoder for å få funksjonene til å fungere skikkelig.

Retningslinjer for bruk av like () og hashcode ()

Du bør bare utføre en er lik() metode for objekter som har samme unike hashcode ID. Du burde ikke henrette er lik() når hashcode ID er annerledes.

Tabell 1. Hashcode-sammenligninger

Hvis den hashcode () sammenligning ...Deretter …
returnerer santhenrette er lik()
returnerer falskikke kjør er lik()

Dette prinsippet brukes hovedsakelig i Sett eller Hash samlinger av ytelsesgrunner.

Regler for sammenligning av objekter

Når en hashcode () sammenligning returnerer falsk, den er lik() metode må også returnere falsk. Hvis hashkoden er forskjellig, er objektene definitivt ikke like.

Tabell 2. Objektsammenligning med hashcode ()

Når sammenligningen av hashcode kommer tilbake ...De er lik() metoden skal returnere ...
ektesant eller usant
falskfalsk

Når er lik() metoden returnerer ekte, betyr det at gjenstandene er like i alle verdier og attributter. I dette tilfellet må også hashcode-sammenligningen være sant.

Tabell 3. Objektsammenligning med lik ()

Når er lik() metoden returnerer ...De hashcode () metoden skal returnere ...
ekteekte
falsksant eller usant

Ta utfordringen like () og hashcode ()!

Det er på tide å teste ferdighetene dine med er lik() og hashcode () metoder. Målet ditt i denne utfordringen er å finne ut resultatet av de to er lik() metode sammenligninger og gjett størrelsen på Sett samling.

For å starte, studer følgende kode nøye:

 public class EqualsHashCodeChallenge {public static void main (String ... doYourBest) {System.out.println (new Simpson ("Bart"). equals (new Simpson ("Bart"))); Simpson overriddenHomer = nye Simpson ("Homer") {public int hashCode () {return (43 + 777) + 1; }}; System.out.println (nye Simpson ("Homer"). Er lik (overriddenHomer)); Set set = new HashSet (Set.of (new Simpson ("Homer"), new Simpson ("Marge"))); set.add (nye Simpson ("Homer")); set.add (overriddenHomer); System.out.println (set.size ()); } statisk klasse Simpson {Strengnavn; Simpson (strengnavn) {this.name = navn; } @Override offentlig boolsk er lik (Objekt obj) {Simpson otherSimpson = (Simpson) obj; returner this.name.equals (otherSimpson.name) && this.hashCode () == otherSimpson.hashCode (); } @Override public int hashCode () {return (43 + 777); }}} 

Husk, analyser koden først, gjett resultatet, og kjør deretter koden. Målet ditt er å forbedre ferdighetene dine med kodeanalyse og absorbere kjerne Java-konsepter for å gjøre koden din kraftigere. Velg svaret ditt før du sjekker riktig svar nedenfor.

 A) true true 4 B) true false 3 C) true false 2 D) false true 3 

Hva skjedde nå? Forstå lik () og hashcode ()

I det første er lik() metodesammenligning, er resultatet ekte fordi tilstanden til objektet er nøyaktig den samme og hashcode () metoden returnerer den samme verdien for begge objektene.

I det andre er lik() metodesammenligning, den hashcode () metoden blir overstyrt for overstyreHomer variabel. Navnet er "Homer" for begge Simpson gjenstander, men hashcode () metoden returnerer en annen verdi for overriddenHomer. I dette tilfellet er det endelige resultatet fra er lik() metoden vil være falsk fordi metoden inneholder en sammenligning med hashkoden.

Du vil kanskje legge merke til at størrelsen på samlingen er satt til å holde tre Simpson gjenstander. La oss sjekke dette på en detaljert måte.

Det første objektet i settet vil bli satt inn normalt:

 nye Simpson ("Homer"); 

Det neste objektet blir også satt inn normalt, fordi det har en annen verdi fra det forrige objektet:

 nye Simpson ("Marge"); 

Til slutt følgende Simpson objektet har samme verdi som det første objektet. I dette tilfellet vil ikke objektet bli satt inn:

 set.add (nye Simpson ("Homer")); 

Som vi vet, overstyreHomer objektet bruker en annen hashcode-verdi enn den normale Simpson (“Homer”) instantiering. Av denne grunn vil dette elementet bli satt inn i samlingen:

 overriddenHomer; 

Fasit

Svaret på denne Java-utfordreren er B. Resultatet vil være:

 true false 3 

Videoutfordring! Feilsøking er lik () og hashcode ()

Feilsøking er en av de enkleste måtene å fullt ut absorbere programmeringskonsepter samtidig som du forbedrer koden din. I denne videoen kan du følge med mens jeg feilsøker og forklarer Java er lik() og hashcode () utfordring.

$config[zx-auto] not found$config[zx-overlay] not found