Programiranje

Primerjava predmetov Java z enakama () in hashcode ()

V tem Java Challenger se boste naučili kako enako () in hashcode () združite, da bodo primerjave predmetov učinkovite in enostavne v programih Java. Preprosto povedano, te metode delujejo skupaj, da preverijo, ali imata dva predmeta enake vrednosti.

Brez enako () in hashcode () morali bi ustvariti zelo veliko "če"primerjave, primerjava vsakega polja iz predmeta. Zaradi tega bi bila koda resnično zmedena in težko berljiva. Skupaj nam ti dve metodi pomagata ustvariti bolj prilagodljivo in povezano kodo.

Pridobite izvorno kodo Java Challengers.

Preglasitev equals () in hashcode () v Javi

Preglasitev metode je tehnika, pri kateri se vedenje nadrejenega razreda ali vmesnika v podrazred znova zapiše (preglasi), da se izkoristi polimorfizem. Vsak Predmet v Javi vključuje enako () in a hashcode () metode, vendar jih je treba preglasiti, da delujejo pravilno.

Da bi razumeli, kako razveljavitev deluje z enako () inhashcode (), lahko preučimo njihovo izvajanje v osnovnih razredih Java. Spodaj je enako () metoda v Predmet razred. Metoda preverja, ali je trenutni primerek enak predhodno prenesenemu Predmet.

 javna logična vrednost je enako (Object obj) {return (this == obj); } 

Ko hashcode () metoda ni razveljavljena, privzeta metoda v Predmet razred bo poklican. To je a izvorna metoda, kar pomeni, da bo izveden v drugem jeziku, kot je C, in bo vrnil nekaj kode glede naslova pomnilnika predmeta. (Ni tako pomembno natančno vedeti, kako deluje ta metoda, razen če pišete kodo JDK.)

 @HotSpotIntrinsicCandidate javni izvorni int hashCode (); 

Ko enako () in hashcode () metode niso razveljavljene, namesto tega boste videli zgornje metode. V tem primeru metode ne izpolnjujejo dejanskega namena enako () in hashcode (), ki naj bi preveril, ali imata dva ali več predmetov enake vrednosti.

Praviloma, ko preglasite enako () morate tudi preglasiti hashcode ().

Primerjava predmetov z enakimi ()

Uporabljamo enako () metoda za primerjavo predmetov v Javi. Da bi ugotovili, ali sta dva predmeta enaka, enako () primerja vrednosti lastnosti predmetov:

 javni razred EqualsAndHashCodeExample {public static void main (String ... equalsExplanation) {System.out.println (new Simpson ("Homer", 35, 120) .equals (new Simpson ("Homer", 35,120))); System.out.println (novo Simpson ("Bart", 10, 120) .equals (novo Simpson ("El Barto", 10, 45))); System.out.println (novo Simpson ("Lisa", 54, 60) .equals (novo Object ())); } statični razred Simpson {ime zasebnega niza; zasebna int starost; zasebna int teža; javni Simpson (Ime niza, int starost, int teža) {this.name = ime; this.age = starost; this.weight = teža; } @Override public boolean equals (Objekt o) {if (this == o) {return true; } if (o == null || getClass ()! = o.getClass ()) {return false; } Simpson simpson = (Simpson) o; vrnitev starosti == simpson.age && weight == simpson.weight && name.equals (simpson.name); }}} 

V prvi primerjavi enako () primerja trenutni primerek predmeta s posredovanim objektom. Če imata oba predmeta enake vrednosti, enako () se bo vrnil prav.

V drugi primerjavi enako ()preveri, ali je posredovani objekt nič, ali če je vpisan kot drug razred. Če gre za drug razred, predmeti niso enaki.

Končno, enako () primerja polja predmetov. Če imata dva predmeta enake vrednosti polj, sta predmeta enaka.

Analiza primerjav objektov

Zdaj pa si oglejmo rezultate teh primerjav v naši glavni () metoda. Najprej primerjamo dve Simpson predmeti:

 System.out.println (novo Simpson ("Homer", 35, 120) .equals (novo Simpson ("Homer", 35, 120))); 

Predmeti tukaj so enaki, tako da bo rezultat prav.

Nato primerjamo dve Simpson spet predmeti:

 System.out.println (novo Simpson("Bart", 10, 45) .equals (novo Simpson("El Barto", 10, 45))); 

Predmeti tukaj so skoraj enaki, vendar se njihovi imeni razlikujeta: Bart in El Barto. Rezultat bo torej napačno.

Na koncu primerjajmo a Simpson objekt in primerek razreda Object:

 System.out.println (novo Simpson("Lisa", 54, 60) .equals (novo Predmet())); 

V tem primeru bo rezultat napačno ker so tipi razredov različni.

je enako () v primerjavi z ==

Na prvi pogled == operater in enako () Zdi se, da metoda počne isto, v resnici pa deluje drugače. The == operator primerja, ali dve referenci objekta usmerjata na isti predmet. Na primer:

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

V prvi primerjavi smo ustvarili dva različna primera Simpson primerov z uporabo novo operater. Zaradi tega spremenljivke homer in homer2 bo kazal na drugačno Predmet sklice v kopici pomnilnika. Torej bomo imeli napačno kot rezultat.

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

V drugi primerjavi preglasimo enako () metoda. V tem primeru bodo primerjana samo imena. Ker ime obeh Simpson predmeti je "Homer" rezultat bo prav.

Enolično prepoznavanje predmetov s hashcode ()

Uporabljamo hashcode () metoda za optimizacijo zmogljivosti pri primerjavi predmetov. Izvršitevhashcode () vrne enolični ID za vsak predmet v vašem programu, kar olajša nalogo primerjave celotnega stanja predmeta.

Če hashcode objekta ni enak hashcode drugega predmeta, ni razloga za izvajanje enako () metoda: samo veste, da oba predmeta nista enaka. Po drugi strani pa, če hashcode je enako, potem morate izvršiti enako () metoda za ugotavljanje, ali so vrednosti in polja enaki.

Tu je praktičen primer z hashcode ().

 javni razred HashcodeConcept {public static void main (String ... hashcodeExample) {Simpson homer = nov Simpson (1, "Homer"); Simpson bart = nov Simpson (2, "Homer"); logična isHashcodeEquals = homer.hashCode () == bart.hashCode (); if (isHashcodeEquals) {System.out.println ("Tudi primerjati z enako metodo."); } else {System.out.println ("Ne bi se smelo primerjati z enako metodo, ker je" + "id drugačen, kar pomeni, da predmeti zagotovo niso enaki."); }} statični razred Simpson {int id; Ime niza; javni Simpson (int id, ime niza) {this.id = id; this.name = ime; } @Override public boolean equals (Object o) if (this == o) return true; if (o == null @Override public int hashCode () {return id;}}} 

A hashcode () ki vedno vrne isto vrednost, je veljavna, vendar ne zelo učinkovita. V tem primeru se bo primerjava vedno vrnila prav, torej enako () metoda bo vedno izvedena. V tem primeru se izboljša učinkovitost.

Uporaba equals () in hashcode () z zbirkami

The Nastavite vmesnik je odgovoren za to, da v a ne bodo vstavljeni podvojeni elementi Nastavite podrazred. Sledi nekaj razredov, ki izvajajo Nastavite vmesnik:

  • HashSet
  • TreeSet
  • LinkedHashSet
  • CopyOnWriteArraySet

V a. Se lahko vstavijo samo unikatni elementi Nastavite, torej, če želite elementu dodati element HashSet razred (na primer), morate najprej uporabiti enako () in hashcode () metode za preverjanje edinstvenosti elementa. Če je enako () in hashcode ()metode v tem primeru niso bile razveljavljene, tvegali bi, da v kodo vstavite podvojene elemente.

V spodnji kodi uporabljamo dodajte metoda za dodajanje novega elementa v a HashSet predmet. Pred dodajanjem novega elementa HashSet preveri, ali element že obstaja v dani zbirki:

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

Če je predmet enak, novega elementa ne bomo vstavili.

Hash zbirke

Nastavite ni edina zbirka, ki jo uporablja enako () in hashcode (). HashMap, Hashtable in LinkedHashMap zahtevajo tudi te metode. Če vidite zbirko s predpono »Hash«, ste praviloma prepričani, da zahteva preglasitev zbirke hashcode () in enako () metode za pravilno delovanje njihovih lastnosti.

Smernice za uporabo enak () in hashcode ()

Izvedite samo enako () za predmete z enakim enoličnim ID-jem hashcode. Moral bi ne izvršiti enako () kadar je ID hashcode drugačen.

Tabela 1. Primerjave šifrirnih kod

Če je hashcode () primerjava ...Potem ...
vrne trueizvršiti enako ()
vrne falsene izvrši enako ()

To načelo se uporablja predvsem v Nastavite ali Hash zbirke zaradi razlogov uspešnosti.

Pravila za primerjavo predmetov

Ko a hashcode () primerjava vrne napačno, enako () metoda mora vrniti tudi false. Če je hashcode drugačen, potem predmeti zagotovo niso enaki.

Tabela 2. Primerjava predmetov s hashcode ()

Ko se vrne primerjava hashcode ...The enako () metoda naj vrne ...
pravpravilno ali napačno
napačnonapačno

Ko enako () metoda vrne prav, to pomeni, da so predmeti enaki v vseh vrednostih in atributih. V tem primeru mora biti resnična tudi primerjava hashcode.

Tabela 3. Primerjava predmetov z enakimi ()

Ko enako () metoda vrne ...The hashcode () metoda naj vrne ...
pravprav
napačnopravilno ali napačno

Sprejmi izziv equals () in hashcode ()!

Čas je, da preizkusite svoje znanje z enako () in hashcode () metode. Vaš cilj v tem izzivu je ugotoviti rezultat obeh enako () primerjave metod in uganite velikost Nastavite zbiranje.

Za začetek natančno preučite naslednjo kodo:

 javni razred EqualsHashCodeChallenge {javna statična void main (String ... doYourBest) {System.out.println (new Simpson ("Bart"). equals (new Simpson ("Bart"))); Simpson overriddenHomer = nov Simpson ("Homer") {public int hashCode () {return (43 + 777) + 1; }}; System.out.println (novo Simpson ("Homer"). Je enako (overriddenHomer)); Set set = new HashSet (Set.of (new Simpson ("Homer"), new Simpson ("Marge"))); set.add (nov Simpson ("Homer")); set.add (overriddenHomer); System.out.println (set.size ()); } statični razred Simpson {Ime niza; Simpson (ime niza) {this.name = ime; } @Override public boolean equals (Object obj) {Simpson otherSimpson = (Simpson) obj; vrni this.name.equals (otherSimpson.name) && this.hashCode () == otherSimpson.hashCode (); } @Override public int hashCode () {return (43 + 777); }}} 

Ne pozabite, najprej analizirajte kodo, uganite rezultat, in nato zaženite kodo. Vaš cilj je izboljšati svoje znanje z analizo kode in absorbirati osnovne koncepte Java, da bo vaša koda zmogljivejša. Izberite svoj odgovor, preden preverite spodnji pravilen odgovor.

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

Kaj se je pravkar zgodilo? Razumevanje enakosti () in hashcode ()

V prvem enako () primerjava metode, rezultat je prav ker je stanje predmeta popolnoma enako in hashcode () metoda vrne enako vrednost za oba predmeta.

V drugem enako () primerjava metode, hashcode () metoda je razveljavljena za overridenHomer spremenljivka. Ime je "Homer" za oba Simpson predmeti, ampak hashcode () vrne drugačno vrednost za overriddenHomer. V tem primeru je končni rezultat enako () metoda bo napačno ker metoda vsebuje primerjavo s hashcode.

Morda boste opazili, da je velikost zbirke nastavljena na tri Simpson predmetov. Preverimo to na podroben način.

Prvi predmet v nizu bo vstavljen normalno:

 novi Simpson ("Homer"); 

Tudi naslednji predmet bo vstavljen normalno, ker ima drugačno vrednost kot prejšnji objekt:

 novi Simpson ("Marge"); 

Na koncu še naslednje Simpson objekt ima enako vrednost kot prvi objekt. V tem primeru predmeta ne bomo vstavili:

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

Kot vemo, overridenHomer objekt uporablja drugačno vrednost hashcode od običajne Simpson ("Homer") instanciranje. Iz tega razloga bo ta element vstavljen v zbirko:

 overriddenHomer; 

Tipka za odgovor

Odgovor na ta izzivalec Java je B. Rezultat bi bil:

 true false 3 

Video izziv! Odpravljanje napak je enako () in hashcode ()

Odpravljanje napak je eden najlažjih načinov za popolno absorpcijo konceptov programiranja, hkrati pa izboljšate kodo. V tem videoposnetku lahko sledite, medtem ko odpravljam napake in razlagam Javo enako () in hashcode () izziv.

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