Programmering

Sammenligning af Java-objekter med lig med () og hashcode ()

Heri Java Challenger du lærer hvordan lige med() og hashcode () kombiner for at gøre objektsammenligning effektiv og nem i dine Java-programmer. Kort sagt, disse metoder arbejder sammen for at kontrollere, om to objekter har de samme værdier.

Uden lige med() og hashcode () vi bliver nødt til at skabe meget store "hvis"sammenligninger, sammenligning af hvert felt fra et objekt. Dette ville gøre koden virkelig forvirrende og svær at læse. Sammen hjælper disse to metoder os med at skabe mere fleksibel og sammenhængende kode.

Få Java Challengers kildekode.

Tilsidesættelse er lig med () og hashcode () i Java

Overordnet metode er en teknik, hvor moderklassen eller interfaceets opførsel er skrevet igen (tilsidesat) i underklassen for at drage fordel af polymorfisme. Hver Objekt i Java inkluderer en lige med() og en hashcode () metode, men de skal tilsidesættes for at fungere korrekt.

At forstå, hvordan overordnet fungerer med lige med() oghashcode (), kan vi studere deres implementering i de centrale Java-klasser. Nedenfor er lige med() metode i Objekt klasse. Metoden kontrollerer, om den aktuelle forekomst er den samme som den tidligere beståede Objekt.

 offentlige boolske er lig med (Objekt obj) {return (dette == obj); } 

Når hashcode () Metoden overstyres ikke, standardmetoden i Objekt klasse påberåbes. Dette er en indfødte metode, hvilket betyder, at det vil blive udført på et andet sprog som C, og vil returnere nogle koder vedrørende objektets hukommelsesadresse. (Det er ikke så vigtigt at vide nøjagtigt, hvordan denne metode fungerer, medmindre du skriver JDK-kode.)

 @HotSpotIntrinsicCandidate offentlig indfødt int hashCode (); 

Når lige med() og hashcode () metoder overstyres ikke, du vil se ovenstående metoder i stedet. I dette tilfælde opfylder metoderne ikke det egentlige formål med lige med() og hashcode (), som er at kontrollere, om to eller flere objekter har de samme værdier.

Som regel når du tilsidesætter lige med() du skal også tilsidesætte hashcode ().

Sammenligning af objekter med lig med ()

Vi bruger lige med() metode til at sammenligne objekter i Java. For at afgøre, om to objekter er ens, lige med() sammenligner værdierne for 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). Lige (nye Simpson ("El Barto", 10, 45)); System.out.println (ny Simpson ("Lisa", 54, 60). Ligestilling (nyt objekt ())); } statisk klasse Simpson {privat strengnavn; privat int alder privat int vægt public Simpson (String name, int age, int weight) {this.name = name; this.age = alder; denne. vægt = vægt; } @ Override offentlige boolske lig (Objekt o) {hvis (dette == o) {returner sandt; } hvis (o == null || getClass ()! = o.getClass ()) {returner false; } Simpson simpson = (Simpson) o; return age == simpson.age && weight == simpson.weight && name.equals (simpson.name); }}} 

I den første sammenligning lige med() sammenligner den aktuelle objektforekomst med det objekt, der er sendt. Hvis de to objekter har de samme værdier, lige med() kommer tilbage rigtigt.

I den anden sammenligning lige med()kontrollerer for at se, om det passerede objekt er nul, eller hvis den er skrevet som en anden klasse. Hvis det er en anden klasse, er objekterne ikke ens.

Langt om længe, lige med() sammenligner objektenes felter. Hvis to objekter har de samme feltværdier, er objekterne de samme.

Analyse af objektsammenligninger

Lad os nu se resultaterne af disse sammenligninger i vores hoved () metode. For det første sammenligner vi to Simpson genstande:

 System.out.println (ny Simpson ("Homer", 35, 120). Ligestilling (ny Simpson ("Homer", 35, 120))); 

Objekterne her er identiske, så resultatet bliver rigtigt.

Dernæst sammenligner vi to Simpson genstande igen:

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

Objekterne her er næsten identiske, men deres navne er forskellige: Bart og El Barto. Derfor bliver resultatet falsk.

Lad os endelig sammenligne en Simpson objekt og en forekomst af klassen Objekt:

 System.out.println (ny Simpson("Lisa", 54, 60). Ligestilling (ny Objekt())); 

I dette tilfælde bliver resultatet falsk fordi klassetyperne er forskellige.

er lig med () versus ==

Ved første øjekast, == operatør og lige med() metoden kan synes at gøre det samme, men i virkeligheden fungerer de forskelligt. Det == operatør sammenligner, om to objekthenvisninger peger på det samme objekt. For eksempel:

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

I den første sammenligning instantierede vi to forskellige Simpson tilfælde, der bruger ny operatør. På grund af dette er variablerne homer og homer2 vil pege på forskellige Objekt referencer i hukommelsesbunken. Så det får vi falsk som resultat.

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

I den anden sammenligning tilsidesætter vi lige med() metode. I dette tilfælde sammenlignes kun navnene. Fordi navnet på begge Simpson objekter er "Homer", resultatet bliver rigtigt.

Entydigt identificere objekter med hashcode ()

Vi bruger hashcode () metode til optimering af ydeevne ved sammenligning af objekter. Udførerhashcode () returnerer et unikt ID for hvert objekt i dit program, hvilket gør opgaven med at sammenligne hele objektets tilstand meget lettere.

Hvis et objekts hashkode ikke er den samme som et andet objekts hashkode, er der ingen grund til at udføre lige med() metode: du ved bare, at de to objekter ikke er de samme. På den anden side, hvis hashkoden er det samme, så skal du udføre lige med() metode til at bestemme, om værdierne og felterne 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 = ny Simpson (2, "Homer"); boolsk isHashcodeEquals = homer.hashCode () == bart.hashCode (); if (isHashcodeEquals) {System.out.println ("Skal sammenlignes med ligemetoden også."); } ellers {System.out.println ("Bør ikke sammenlignes med ligemetoden, fordi" + "id'et er anderledes, det betyder, at objekterne ikke er lig med sikkerhed."); }} statisk klasse Simpson {int id; Strengnavn; offentlig Simpson (int id, strengnavn) {this.id = id; dette.navn = navn; } @ Override offentlige boolske er lig med (Objekt o) hvis (dette == o) returnerer sandt; hvis (o == null @ Override public int hashCode () {return id;}}} 

EN hashcode () der altid returnerer den samme værdi er gyldig, men ikke særlig effektiv. I dette tilfælde vil sammenligningen altid vende tilbage rigtigt, så lige med() metode vil altid blive udført. Der er ingen forbedring af ydeevnen i dette tilfælde.

Brug af lig med () og hashcode () med samlinger

Det Sæt interface er ansvarlig for at sikre, at der ikke indsættes duplikatelementer i en Sæt underklasse. Følgende er nogle af de klasser, der implementerer Sæt grænseflade:

  • HashSet
  • TreeSet
  • LinkedHashSet
  • CopyOnWriteArraySet

Kun unikke elementer kan indsættes i en Sæt, så hvis du vil føje et element til HashSet klasse (for eksempel), skal du først bruge lige med() og hashcode () metoder til at kontrollere, at elementet er unikt. Hvis den lige med() og hashcode ()metoder blev ikke tilsidesat i dette tilfælde, risikerer du at indsætte duplikatelementer i koden.

I nedenstående kode bruger vi tilføje metode til at tilføje et nyt element til en HashSet objekt. Før det nye element tilføjes, HashSet kontrollerer for at se, om elementet allerede findes i den givne samling:

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

Hvis objektet er det samme, indsættes det nye element ikke.

Hash samlinger

Sæt er ikke den eneste samling, der gør brug af lige med() og hashcode (). HashMap, Hashtable og LinkedHashMap kræver også disse metoder. Hvis du ser en samling, der har præfikset "Hash", kan du som regel være sikker på, at den kræver tilsidesættelse af hashcode () og lige med() metoder til at få deres funktioner til at fungere korrekt.

Retningslinjer for brug af lig med () og hashcode ()

Du skal kun udføre en lige med() metode til objekter, der har det samme unikke hashcode-id. Du burde ikke udføre lige med() når hashcode-id'et er anderledes.

Tabel 1. Hashcode-sammenligninger

Hvis den hashcode () sammenligning ...Derefter …
returnerer sandtudføre lige med()
returnerer falskudfør ikke lige med()

Dette princip bruges hovedsageligt i Sæt eller Hash samlinger af ydeevneårsager.

Regler for sammenligning af objekter

Når en hashcode () sammenligning vender tilbage falsk, det lige med() metode skal også returnere falsk. Hvis hashkoden er forskellig, er objekterne bestemt ikke ens.

Tabel 2. Objektsammenligning med hashcode ()

Når sammenligningen af ​​hashcode vender tilbage ...Det lige med() metoden skal vende tilbage ...
rigtigtsandt eller falsk
falskfalsk

Når lige med() metoden vender tilbage rigtigtbetyder det, at objekterne er ens i alle værdier og attributter. I dette tilfælde skal sammenligningen af ​​hashcode også være sand.

Tabel 3. Objektsammenligning med lig med ()

Når lige med() metoden vender tilbage ...Det hashcode () metoden skal vende tilbage ...
rigtigtrigtigt
falsksandt eller falsk

Tag udfordringen lig () og hashcode ()!

Det er tid til at teste dine færdigheder med lige med() og hashcode () metoder. Dit mål i denne udfordring er at finde ud af produktionen af ​​de to lige med() metode sammenligninger og gætte størrelsen på Sæt kollektion.

For at starte skal du studere følgende kode omhyggeligt:

 public class EqualsHashCodeChallenge {public static void main (String ... doYourBest) {System.out.println (ny Simpson ("Bart"). er lig med (ny Simpson ("Bart"))); Simpson overriddenHomer = ny Simpson ("Homer") {public int hashCode () {return (43 + 777) + 1; }}; System.out.println (ny Simpson ("Homer"). Er lig med (overriddenHomer)); Set set = new HashSet (Set.of (new Simpson ("Homer"), new Simpson ("Marge"))); set.add (ny Simpson ("Homer")); set.add (tilsidesatHomer); System.out.println (set.size ()); } statisk klasse Simpson {Strengnavn; Simpson (strengnavn) {this.name = navn; } @ Override offentlige boolske lig (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 først koden, gæt resultatet, og kør derefter koden. Dit mål er at forbedre din dygtighed med kodeanalyse og absorbere centrale Java-koncepter for at gøre din kode mere kraftfuld. Vælg dit svar, før du kontrollerer det rigtige svar nedenfor.

 A) sand sand 4 B) sand falsk 3 C) sand falsk 2 D) falsk sand 3 

Hvad skete der lige? Forståelse lig med () og hashcode ()

Først og fremmest lige med() metode sammenligning, resultatet er rigtigt fordi objektets tilstand er nøjagtig den samme og hashcode () metode returnerer den samme værdi for begge objekter.

I det andet lige med() metode sammenligning, hashcode () metoden bliver tilsidesat for overridenHomer variabel. Navnet er "Homer" for begge Simpson genstande, men hashcode () metode returnerer en anden værdi for overriddenHomer. I dette tilfælde er det endelige resultat fra lige med() metode vil være falsk fordi metoden indeholder en sammenligning med hashkoden.

Du bemærker måske, at størrelsen på samlingen er indstillet til at rumme tre Simpson genstande. Lad os kontrollere dette på en detaljeret måde.

Det første objekt i sættet vil blive indsat normalt:

 nye Simpson ("Homer"); 

Det næste objekt indsættes også normalt, fordi det har en anden værdi end det forrige objekt:

 nye Simpson ("Marge"); 

Endelig følgende Simpson objekt har samme værdi som det første objekt. I dette tilfælde indsættes objektet ikke:

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

Som vi ved, er overridenHomer objekt bruger en anden hashcode-værdi end den normale Simpson (“Homer”) instantiering. Af denne grund indsættes dette element i samlingen:

 tilsidesatHomer; 

Svar nøgle

Svaret på denne Java-udfordrer er B. Outputtet ville være:

 sandt falsk 3 

Video udfordring! Fejlfinding er lig med () og hashcode ()

Fejlfinding er en af ​​de nemmeste måder til fuldt ud at absorbere programmeringskoncepter, samtidig med at du forbedrer din kode. I denne video kan du følge med, mens jeg fejler og forklarer Java lige med() og hashcode () udfordring.

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