Programavimas

„Java“ objektų palyginimas su lygiais () ir maišos kodu ()

Šiame „Java Challenger“ sužinosite kaip lygi () ir maišos kodas () sujungti, kad objektų palyginimas būtų efektyvus ir paprastas jūsų „Java“ programose. Paprasčiau tariant, šie metodai veikia kartu siekiant patikrinti, ar dviejų objektų vertės yra vienodos.

Be lygi () ir maišos kodas () mes turėtume sukurti labai didelius "jei"palyginimai, lyginant kiekvieną objekto lauką. Tai padarytų kodą tikrai painų ir sunkiai įskaitomą. Kartu šie du metodai padeda sukurti lankstesnį ir darnesnį kodą.

Gaukite „Java Challengers“ šaltinio kodą.

„Java“ lygus () ir maišos kodas ()

Metodas svarbesnis yra metodas, kai tėvų klasės ar sąsajos elgesys vėl užrašomas (perrašomas) poklasyje, kad būtų galima pasinaudoti polimorfizmu. Kiekvienas Objektas „Java“ apima lygi () ir a maišos kodas () metodas, tačiau jie turi būti nepaisomi, kad jie veiktų tinkamai.

Suprasti, kaip veikia nepaisoma lygi () irmaišos kodas (), galime ištirti jų įgyvendinimą pagrindinėse „Java“ klasėse. Žemiau yra lygi () metodas Objektas klasė. Šiuo metodu tikrinama, ar dabartinis egzempliorius sutampa su anksčiau perduotu Objektas.

 viešoji loginė reikšmė lygi (Object obj) {return (this == obj); } 

Kai maišos kodas () metodas nepaisomas, numatytasis metodas Objektas klasė bus iškviesta. Tai yra vietinis metodas, tai reiškia, kad jis bus vykdomas kita kalba, pvz., C, ir grąžins tam tikrą kodą, susijusį su objekto atminties adresu. (Ne taip svarbu tiksliai žinoti, kaip veikia šis metodas, nebent rašote JDK kodą.)

 @HotSpotIntrinsicCandidate public native int hashCode (); 

Kai lygi () ir maišos kodas () metodai nepaisomi, vietoj to pamatysite aukščiau nurodytus metodus. Šiuo atveju metodai neatitinka tikrojo tikslo lygi () ir maišos kodas (), kuris yra patikrinti, ar dviejų ar daugiau objektų vertės yra vienodos.

Paprastai, kai jūs nepaisote lygi () taip pat turite nepaisyti maišos kodas ().

Objektų palyginimas su lygiais ()

Mes naudojame lygi () „Java“ objektų palyginimo metodas. Norėdami nustatyti, ar du objektai yra vienodi, lygi () palygina objektų atributų vertes:

 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 (naujas „Simpson“ („Bart“, 10, 120). Yra lygus (naujas „Simpson“ („El Barto“, 10, 45))); System.out.println (naujas „Simpson“ („Lisa“, 54, 60). Yra lygus (naujas objektas ())); } statinė klasė Simpson {private String name; privatus int amžius; privatus int svoris; public Simpson (Stygos vardas, int amžius, int svoris) {this.name = vardas; tai. amžius = amžius; tai.svoris = svoris; } @Paisyti viešosios loginės loginės vertės lygu (Objekto o) {if (this == o) {return true; } if (o == null || getClass ()! = o.getClass ()) {grąžinti klaidingą; } Simpsonas simpsonas = (Simpsonas) o; grįžimo amžius == simpson.age && weight == simpson.weight && name.equals (simpson.name); }}} 

Pirmajame palyginime lygi () palygina esamą objekto egzempliorių su perduotu objektu. Jei šių dviejų objektų vertės yra vienodos, lygi () grįš tiesa.

Antrame palyginime lygi ()patikrina, ar perduotas objektas yra niekinisarba jei ji įvesta kaip kita klasė. Jei tai kita klasė, objektai nėra lygūs.

Pagaliau, lygi () palygina objektų laukus. Jei du objektai turi tas pačias lauko reikšmes, tada objektai yra vienodi.

Analizuojant objektų palyginimus

Pažvelkime į šių palyginimų rezultatus pagrindinis () metodas. Pirma, mes palyginame du Simpsonas objektai:

 System.out.println (naujas „Simpson“ („Homer“, 35, 120). Yra lygus (naujas „Simpson“ („Homer“, 35, 120))); 

Objektai čia yra identiški, todėl rezultatas bus tiesa.

Toliau palyginsime du Simpsonas vėl objektai:

 System.out.println (nauja Simpsonas(„Bart“, 10, 45). Lygi (nauja Simpsonas(„El Barto“, 10, 45))); 

Objektai čia beveik identiški, tačiau jų pavadinimai skiriasi: Bartas ir El Barto. Todėl rezultatas bus melagingas.

Galiausiai palyginkime a Simpsonas objektas ir objekto klasės egzempliorius:

 System.out.println (nauja Simpsonas("Lisa", 54, 60). Lygi (nauja Objektas())); 

Tokiu atveju rezultatas bus melagingas nes klasių tipai yra skirtingi.

lygi () ir ==

Iš pirmo žvilgsnio == operatorius ir lygi () Atrodo, kad metodas daro tą patį, bet iš tikrųjų jie veikia kitaip. == operatorius palygina, ar dvi objekto nuorodos nurodo tą patį objektą. Pavyzdžiui:

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

Pirmajame palyginime mes išaiškinome du skirtingus Simpsonas atvejų naudojant naujas operatorius. Dėl to kintamieji homeris ir homeris2 nurodys į skirtingus Objektas nuorodos atminties krūvoje. Taigi turėsime melagingas kaip rezultatas.

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

Antrame palyginime mes nepaisome lygi () metodas. Tokiu atveju bus lyginami tik vardai. Nes abiejų vardas Simpsonas objektai yra „Homeras“, rezultatas bus tiesa.

Objektų unikalus identifikavimas naudojant maišos kodą ()

Mes naudojame maišos kodas () būdas optimizuoti našumą lyginant objektus. Vykdomamaišos kodas () grąžina unikalų kiekvieno jūsų programos objekto ID, kuris žymiai palengvina užduotį palyginti visą objekto būseną.

Jei objekto maišos kodas nėra tas pats, kas kito objekto maišos kodas, nėra jokios priežasties vykdyti lygi () metodas: jūs tiesiog žinote, kad du objektai nėra vienodi. Kita vertus, jei maišos kodas yra tas pats, tada jūs turite įvykdyti lygi () metodas, siekiant nustatyti, ar reikšmės ir laukai yra vienodi.

Štai praktinis pavyzdys su maišos kodas ().

 public class HashcodeConcept {public static void main (String ... hashcodeExample) {Simpson homer = new Simpson (1, "Homer"); Simpsono bartas = naujasis Simpsonas (2, „Homeras“); loginis yra isHashcodeEquals = homer.hashCode () == bart.hashCode (); if (isHashcodeEquals) {System.out.println ("Turėtų būti lyginamas ir su lygių metodu."); } else {System.out.println ("Neturėtų lyginti su metodu„ lygu “, nes„ + “ID yra kitoks, tai reiškia, kad objektai tikrai nėra lygūs."); }} statinė klasė Simpsonas {int id; Stygos pavadinimas; public Simpson (int id, String name) {this.id = id; this.name = vardas; } @Paisyti viešosios loginės loginės vertės lygu (Object o) if (this == o) return true; if (o == null @ Nepaisyti viešojo int hashCode () {return ID;}}} 

A maišos kodas () visada grąžina tą pačią vertę, galioja, bet nėra labai efektyvi. Tokiu atveju palyginimas visada grįš tiesa, Taigi lygi () metodas visada bus vykdomas. Šiuo atveju pagerėjimo nėra.

Naudojant lygias () ir maišos kodą () su kolekcijomis

Nustatyti sąsaja yra atsakinga už tai, kad į a. nebūtų dedami pasikartojantys elementai Nustatyti poklasis. Toliau pateikiamos kelios klasės, kurios įgyvendina Nustatyti sąsaja:

  • „HashSet“
  • Medžių rinkinys
  • „LinkedHashSet“
  • „CopyOnWriteArraySet“

Į a. Galima įterpti tik unikalius elementus Nustatyti, taigi, jei norite pridėti elementą prie „HashSet“ klasės (pavyzdžiui), pirmiausia turite naudoti lygi () ir maišos kodas () metodai, skirti patikrinti, ar elementas yra unikalus. Jei lygi () ir maišos kodas ()metodai šiuo atveju nebuvo nepaisyti, rizikuojate į kodą įterpti pasikartojančius elementus.

Žemiau esančiame kode naudojame papildyti metodas pridėti naują elementą prie a „HashSet“ objektas. Prieš pridedant naują elementą, „HashSet“ patikrina, ar elementas jau yra pateiktoje kolekcijoje:

 if (e.hash == maišos && ((k = e.key) == raktas || (raktas! = null && raktas.lygus (k)))) pertrauka; p = e; 

Jei objektas yra tas pats, naujas elementas nebus įterptas.

Hash kolekcijos

Nustatyti nėra vienintelė kolekcija, kuria naudojamasi lygi () ir maišos kodas (). „HashMap“, „Hashtable“ ir „LinkedHashMap“ taip pat reikalingi šie metodai. Paprastai, jei matote kolekciją, kurios priešdėlis yra „Hash“, galite būti tikri, kad jai reikia nepaisyti maišos kodas () ir lygi () metodus, kad jų funkcijos veiktų tinkamai.

Lygių () ir maišos kodų () naudojimo gairės

Turėtumėte vykdyti tik lygi () metodas objektams, turintiems tą patį unikalų maišos kodo ID. Tu turėtum ne vykdyti lygi () kai maišos kodo ID yra kitoks.

1 lentelė. „Hashcode“ palyginimai

Jei maišos kodas () palyginimas ...Tada ...
grįžta tiesavykdyti lygi ()
grąžina klaidingąnevykdyti lygi ()

Šis principas dažniausiai naudojamas Nustatyti arba Hashas kolekcijos dėl našumo priežasčių.

Objektų palyginimo taisyklės

Kada maišos kodas () palyginimas grąžina melagingas, lygi () metodas taip pat turi grąžinti klaidingą. Jei maišos kodas yra kitoks, tada objektai tikrai nėra lygūs.

2 lentelė. Objektų palyginimas su maišos kodu ()

Grįžus maišos kodo palyginimui ... lygi () metodas turėtų grįžti ...
tiesatiesa ar melas
melagingasmelagingas

Kai lygi () metodas grąžinamas tiesa, tai reiškia, kad objektai yra lygūs visose vertybėse ir atributuose. Šiuo atveju maišos kodo palyginimas taip pat turi būti teisingas.

3 lentelė. Objektų palyginimas su lygiais ()

Kai lygi () metodas grąžina ... maišos kodas () metodas turėtų grįžti ...
tiesatiesa
melagingastiesa ar melas

Paimkite lygių () ir maišos () iššūkį!

Atėjo laikas išbandyti savo įgūdžius lygi () ir maišos kodas () metodai. Jūsų tikslas šiame iššūkyje yra išsiaiškinti jų du rezultatus lygi () metodų palyginimus ir atspėti Nustatyti kolekcija.

Norėdami pradėti, atidžiai išstudijuokite šį kodą:

 public class EqualsHashCodeChallenge {public static void main (String ... doYourBest) {System.out.println (naujas Simpsonas ("Bart"). lygu (naujas Simpsonas ("Bart"))); Simpsonas overriddenHomer = naujas Simpsonas ("Homeras") {public int hashCode () {return (43 + 777) + 1; }}; System.out.println (naujas Simpsonas („Homeris“). Lygu (overriddenHomer)); Set set = new HashSet (Set.of (naujas Simpsonas („Homeris“), naujas „Simpsonas“ („Marge“))); set.add (naujasis Simpsonas („Homeras“)); set.add (overriddenHomer); System.out.println (set.size ()); } statinė klasė Simpsonas {Stygos pavadinimas; Simpsonas (eilutės pavadinimas) {this.name = vardas; } @Paisyti viešosios loginės loginės vertės lygus (Object obj) {Simpson otherSimpson = (Simpson) obj; grąžinkite this.name.equals (otherSimpson.name) && this.hashCode () == otherSimpson.hashCode (); } @Paisyti viešąjį int hashCode () {return (43 + 777); }}} 

Prisiminkite, pirmiausia išanalizuokite kodą, atspėkite rezultatą, ir tada paleiskite kodą. Jūsų tikslas yra patobulinti savo įgūdžius analizuojant kodą ir įsisavinti pagrindines „Java“ sąvokas, kad jūsų kodas taptų galingesnis. Pasirinkite savo atsakymą prieš patikrindami teisingą atsakymą žemiau.

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

Kas ką tik nutiko? Suprasti lygų () ir maišos kodą ()

Pirmajame lygi () metodo palyginimas, rezultatas yra tiesa nes objekto būsena yra visiškai ta pati ir maišos kodas () metodas grąžina tą pačią abiejų objektų vertę.

Antroje lygi () metodo palyginimas maišos kodas () metodas yra nepaisomas overridenHomer kintamasis. Abiejų vardas yra „Homeris“ Simpsonas objektai, bet maišos kodas () metodas pateikia kitokią reikšmę overriddenHomer. Šiuo atveju galutinis rezultatas iš lygi () metodas bus melagingas nes metodas yra palyginimas su maišos kodu.

Galite pastebėti, kad kolekcijos dydis nustatytas laikant tris Simpsonas objektai. Patikrinkime tai išsamiai.

Pirmasis rinkinio objektas bus įterptas paprastai:

 naujasis Simpsonas („Homeras“); 

Kitas objektas taip pat bus įterptas įprastai, nes jis turi skirtingą vertę nei ankstesnis objektas:

 naujasis Simpsonas („Marge“); 

Galiausiai taip Simpsonas objektas turi tą pačią vertę kaip ir pirmasis objektas. Tokiu atveju objektas nebus įterptas:

 set.add (naujasis Simpsonas („Homeras“)); 

Kaip žinome, overridenHomer objektas naudoja kitokią maišos kodo reikšmę nei įprasta Simpsonas („Homeras“) akimirksniu. Dėl šios priežasties šis elementas bus įterptas į kolekciją:

 nepaisomaHomeras; 

Atsakymo raktas

Atsakymas į šį „Java“ varžovą yra B. Rezultatas būtų:

 tikroji klaidinga 3 

Vaizdo iššūkis! Derinimas lygus () ir maišos kodas ()

Derinimas yra vienas iš paprasčiausių būdų visiškai įsisavinti programavimo koncepcijas, kartu tobulinant kodą. Šiame vaizdo įraše galite sekti, kol aš derinu ir paaiškinu „Java“ lygi () ir maišos kodas () iššūkis.