Programovanie

Porovnanie objektov Java s equals () a hashcode ()

V tomto Java Challenger naučíte sa ako rovná sa () a hashcode () kombinujte, aby bolo porovnávanie objektov vo vašich programoch Java efektívne a ľahké. Jednoducho povedané, tieto metódy spolupracujú na overení, či majú dva objekty rovnaké hodnoty.

Bez rovná sa () a hashcode () museli by sme vytvoriť veľmi veľké “ak"porovnania, porovnanie každého poľa z objektu. Takto by bol kód skutočne neprehľadný a ťažko čitateľný. Spoločne nám tieto dve metódy pomáhajú vytvárať flexibilnejší a súdržnejší kód."

Získajte zdrojový kód Java Challengers.

Prepísanie equals () a hashcode () v Jave

Prepísanie metódy je technika, pri ktorej sa správanie nadradenej triedy alebo rozhrania znova zapisuje (prepíše) do podtriedy, aby sa využila výhoda polymorfizmu. Každý Objekt v Jave obsahuje rovná sa () a a hashcode () musia byť prekonané, aby správne fungovali.

Aby sme pochopili, ako funguje prvoradé nastavenie rovná sa () ahashcode (), môžeme ich implementáciu študovať v základných triedach Java. Nižšie je rovná sa () metóda v Objekt trieda. Metóda kontroluje, či je aktuálna inštancia rovnaká ako predtým odovzdaná Objekt.

 public boolean equals (Object obj) {return (this == obj); } 

Keď hashcode () metóda nie je prepísaná, predvolená metóda v Objekt triedy bude vyvolané. Toto je natívna metóda, čo znamená, že sa vykoná v inom jazyku, napríklad C, a vráti nejaký kód týkajúci sa adresy pamäte objektu. (Nie je až také dôležité presne vedieť, ako táto metóda funguje, pokiaľ nepíšete kód JDK.)

 @HotSpotIntrinsicCandidate public native int hashCode (); 

Keď rovná sa () a hashcode () metódy nie sú prepísané, namiesto toho uvidíte vyššie uvedené metódy. V takom prípade metódy nespĺňajú skutočný účel metódy rovná sa () a hashcode (), čo je kontrola, či majú dva alebo viac objektov rovnaké hodnoty.

Spravidla, keď prepíšete rovná sa () musíte tiež prepísať hashcode ().

Porovnanie objektov s equals ()

Používame rovná sa () metóda na porovnanie objektov v Jave. S cieľom zistiť, či sú dva objekty rovnaké, rovná sa () porovnáva hodnoty atribútov objektov:

 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 (nový Simpson („Bart“, 10, 120) .equals (nový Simpson („El Barto“, 10, 45))); System.out.println (nový Simpson ("Lisa", 54, 60) .equals (nový objekt ())); } statická trieda Simpson {súkromné ​​meno reťazca; súkromný int vek; súkromná int váha; public Simpson (názov reťazca, int vek, int váha) {this.name = meno; this.age = vek; this.weight = weight; } @Override public boolean equals (Object o) {if (this == o) {return true; } if (o == null || getClass ()! = o.getClass ()) {return false; } Simpson simpson = (Simpson) o; návratový vek == simpson.age && váha == simpson.weight && name.equals (simpson.name); }}} 

V prvom porovnaní rovná sa () porovnáva aktuálnu inštanciu objektu s objektom, ktorý bol odovzdaný. Ak majú dva objekty rovnaké hodnoty, rovná sa () vráti sa pravda.

V druhom porovnaní rovná sa ()skontroluje, či je odovzdaný objekt nulový, alebo ak je napísaný ako iná trieda. Ak je to iná trieda, objekty si nie sú rovnaké.

Nakoniec rovná sa () porovnáva polia objektov. Ak majú dva objekty rovnaké hodnoty poľa, sú tieto objekty rovnaké.

Analýza porovnaní objektov

Pozrime sa teraz na výsledky týchto porovnaní v našom hlavný() metóda. Najskôr porovnáme dve Simpson objekty:

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

Objekty sú tu identické, takže výsledok bude pravda.

Ďalej porovnávame dva Simpson objekty znova:

 System.out.println (nový Simpson(„Bart“, 10, 45) .equals (nové Simpson(„El Barto“, 10, 45))); 

Objekty sú takmer totožné, ale ich názvy sú odlišné: Bart a El Barto. Preto bude výsledok nepravdivé.

Na záver si porovnajme a Simpson objekt a inštancia triedy Object:

 System.out.println (nový Simpson(„Lisa“, 54, 60) .equals (nové Objekt())); 

V takom prípade bude výsledok nepravdivé pretože typy tried sú rôzne.

rovná sa () verzus ==

Na prvý pohľad == operátor a rovná sa () Môže sa zdať, že metóda robí to isté, ale v skutočnosti fungujú inak. The == operátor porovnáva, či dva odkazy na objekty smerujú na ten istý objekt. Napríklad:

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

V prvom porovnaní sme vytvorili inštanciu dvoch rôznych Simpson inštancie používajúce Nový operátor. Z tohto dôvodu premenné homer a homer2 bude ukazovať na iné Objekt odkazy v halde pamäte. Takže budeme nepravdivé ako výsledok.

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

V druhom porovnaní prepíšeme rovná sa () metóda. V takom prípade sa budú porovnávať iba mená. Pretože meno oboch Simpson objektov je „Homer“, výsledkom bude pravda.

Jedinečná identifikácia objektov pomocou hashcode ()

Používame hashcode () metóda na optimalizáciu výkonu pri porovnávaní objektov. Vykonávaniehashcode () vráti jedinečné ID pre každý objekt vo vašom programe, čo výrazne uľahčí porovnávanie celého stavu objektu.

Ak hashcode objektu nie je rovnaký ako hashcode iného objektu, nie je dôvod ho vykonávať rovná sa () metóda: len viete, že dva objekty nie sú rovnaké. Na druhej strane, ak má hashcode je to isté, potom musíte vykonať rovná sa () metóda na určenie, či sú hodnoty a polia rovnaké.

Tu je praktický príklad s hashcode ().

 public class HashcodeConcept {public static void main (String ... hashcodeExample) {Simpson homer = new Simpson (1, "Homer"); Simpsonov bart = nový Simpson (2, „Homer“); boolean isHashcodeEquals = homer.hashCode () == bart.hashCode (); if (isHashcodeEquals) {System.out.println ("Malo by sa porovnávať aj s metódou rovných."); } else {System.out.println ("Nemalo by sa porovnávať s metódou equals, pretože" + "je id iné, to znamená, že objekty nie sú určite rovnaké."); }} statická trieda Simpson {int id; Názov reťazca; public Simpson (int id, String name) {this.id = id; this.name = meno; } @Override public boolean equals (Object o) if (this == o) return true; if (o == null @Override public int hashCode () {return id;}}} 

A hashcode () ktorá vždy vráti rovnakú hodnotu, je platná, ale nie veľmi efektívna. V takom prípade sa porovnanie vždy vráti pravda, takže rovná sa () metóda sa vykoná vždy. V tomto prípade nedôjde k zlepšeniu výkonu.

Používanie equals () a hashcode () so zbierkami

The Nastaviť Rozhranie je zodpovedné za zabezpečenie toho, že do a. nebudú vložené duplicitné prvky Nastaviť podtrieda. Nasleduje niekoľko tried, ktoré implementujú Nastaviť rozhranie:

  • HashSet
  • TreeSet
  • LinkedHashSet
  • CopyOnWriteArraySet

Do a. Môžu byť vložené iba jedinečné prvky Nastaviť, takže ak chcete pridať prvok do súboru HashSet triedy (napríklad), musíte najskôr použiť rovná sa () a hashcode () metódy na overenie jedinečnosti prvku. Ak rovná sa () a hashcode ()metódy v tomto prípade neboli prepísané, riskovali by ste vloženie duplicitných prvkov do kódu.

V kóde nižšie používame pridať metóda na pridanie nového prvku do a HashSet objekt. Pred pridaním nového prvku HashSet skontroluje, či prvok v danej kolekcii už existuje:

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

Ak je objekt rovnaký, nový prvok sa nevloží.

Hash zbierky

Nastaviť nie je jediná zbierka, ktorá využíva rovná sa () a hashcode (). Tieto metódy vyžadujú aj programy HashMap, Hashtable a LinkedHashMap. Spravidla platí, že ak vidíte kolekciu, ktorá má predponu „Hash“, môžete si byť istí, že vyžaduje prepísanie hashcode () a rovná sa () metódy na správne fungovanie ich funkcií.

Pokyny na používanie metód equals () a hashcode ()

Mali by ste vykonať iba príkaz rovná sa () metóda pre objekty, ktoré majú rovnaké jedinečné ID hashcode. Mal by si nie vykonať rovná sa () keď je ID hashcode odlišné.

Tabuľka 1. Porovnania kódu Hashcode

Ak hashcode () porovnanie ...Potom ...
vracia sa pravdavykonať rovná sa ()
vráti nepravdivénevykonávať rovná sa ()

Tento princíp sa používa hlavne v Nastaviť alebo Hash zbierky z výkonnostných dôvodov.

Pravidlá pre porovnávanie objektov

Keď hashcode () porovnanie sa vráti nepravdivé, rovná sa () metóda musí tiež vrátiť false. Ak je hashcode iný, potom objekty určite nie sú rovnaké.

Tabuľka 2. Porovnanie objektov s hashcode ()

Keď sa porovnanie hashcode vráti ...The rovná sa () metóda by sa mala vrátiť ...
pravdapravda alebo lož
nepravdivénepravdivé

Keď rovná sa () metóda sa vráti pravda, to znamená, že objekty sú si rovné vo všetkých hodnotách a atribútoch. V takom prípade musí byť pravdivé aj porovnanie hashcode.

Tabuľka 3. Porovnanie objektov s equals ()

Keď rovná sa () metóda vracia ...The hashcode () metóda by sa mala vrátiť ...
pravdapravda
nepravdivépravda alebo lož

Vezmite výzvu equals () a hashcode ()!

Je čas vyskúšať si svoje schopnosti pomocou rovná sa () a hashcode () metódy. Vaším cieľom v tejto výzve je zistiť výstup z týchto dvoch rovná sa () porovnanie metód a hádajte veľkosť súboru Nastaviť zbierka.

Najskôr si pozorne preštudujte nasledujúci kód:

 verejná trieda EqualsHashCodeChallenge {public static void main (String ... doYourBest) {System.out.println (nový Simpson ("Bart"). equals (nový Simpson ("Bart"))); Simpson overriddenHomer = nový Simpson ("Homer") {public int hashCode () {návrat (43 + 777) + 1; }}; System.out.println (nový Simpson ("Homer"). Equals (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 ()); } statická trieda Simpson {Názov reťazca; Simpson (názov reťazca) {this.name = meno; } @Override public boolean equals (Object obj) {Simpson otherSimpson = (Simpson) obj; vrátiť this.name.equals (otherSimpson.name) && this.hashCode () == otherSimpson.hashCode (); } @Override public int hashCode () {return (43 + 777); }}} 

Pamätajte, najskôr analyzujte kód, hádajte výsledok, a potom spustite kód. Vaším cieľom je zlepšiť svoje schopnosti pomocou analýzy kódu a absorbovať základné koncepty Java, aby bol váš kód výkonnejší. Pred kontrolou správnej odpovede nižšie si vyberte svoju odpoveď.

 A) pravda pravda 4 B) pravda nepravda 3 C) pravda nepravda 2 D) nepravda pravda 3 

Čo sa práve stalo? Pochopenie equals () a hashcode ()

V prvom rovná sa () výsledkom je porovnanie metódy pravda pretože stav objektu je úplne rovnaký a hashcode () metóda vráti rovnakú hodnotu pre oba objekty.

V druhom rovná sa () porovnanie metód hashcode () metóda je prepísaná pre prepísaťHomer premenná. Názov pre oboch je „Homér“ Simpson predmety, ale hashcode () metóda vracia inú hodnotu pre overriddenHomer. V takom prípade je konečný výsledok z rovná sa () metóda bude nepravdivé pretože metóda obsahuje porovnanie s hašovacím kódom.

Môžete si všimnúť, že veľkosť zbierky je nastavená na tri Simpson predmety. Poďme to skontrolovať podrobne.

Prvý objekt v množine bude, bude vložený normálne:

 nový Simpson („Homer“); 

Nasledujúci objekt sa vloží tiež normálne, pretože obsahuje inú hodnotu ako predchádzajúci objekt:

 nový Simpson („Marge“); 

Na záver nasledovné Simpson objekt má rovnakú hodnotu ako prvý objekt. V takom prípade nebude objekt vložený:

 set.add (nový Simpson („Homer“)); 

Ako vieme, prepísaťHomer objekt používa inú hodnotu hashcode ako normálna Simpson („Homér“) inštancia. Z tohto dôvodu bude tento prvok vložený do zbierky:

 overriddenHomer; 

Odpovedať kľúč

Odpoveď na tohto vyzývateľa v jazyku Java je B. Výstup by bol:

 pravda nepravda 3 

Video výzva! Ladenie equals () a hashcode ()

Ladenie je jedným z najjednoduchších spôsobov, ako úplne absorbovať programovacie koncepty a zároveň vylepšiť váš kód. V tomto videu môžete sledovať, kým ladím a vysvetľujem Javu rovná sa () a hashcode () výzva.

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