Ohjelmointi

Java-objektien vertaaminen yhtälöllä () ja hashcodeilla ()

Tässä Java Challenger opit kuinka on yhtä suuri () ja hash koodin() Yhdistä tehdäksesi objektien vertailusta tehokasta ja helppoa Java-ohjelmissasi. Yksinkertaisesti sanottuna nämä menetelmät yhdessä tarkastavat, onko kahdella objektilla samat arvot.

Ilman on yhtä suuri () ja hash koodin() meidän olisi luotava erittäin suuria "jos"vertailut, kohteen jokaisen kentän vertaaminen. Tämä tekisi koodista todella hämmentävän ja vaikeasti luettavan. Nämä kaksi menetelmää yhdessä auttavat meitä luomaan joustavamman ja yhtenäisemmän koodin.

Hanki Java Challengers -lähdekoodi.

Yläosien () ja hashcode () korvaaminen Java-ohjelmassa

Menetelmä syrjäyttää on tekniikka, jossa yläluokan tai käyttöliittymän käyttäytyminen kirjoitetaan uudelleen (ohitetaan) alaluokkaan polymorfismin hyödyntämiseksi. Joka Esine Java sisältää on yhtä suuri () ja a hash koodin() mutta ne on ohitettava toimiakseen kunnolla.

Ymmärtää kuinka ohittaminen toimii on yhtä suuri () jahash koodin(), voimme tutkia niiden toteutusta Java-ydinluokissa. Alla on on yhtä suuri () menetelmä Esine luokassa. Menetelmä tarkistaa, onko nykyinen esiintymä sama kuin aiemmin välitetty Esine.

 julkinen totuusarvo on yhtä suuri (Object obj) {return (this == obj); } 

Kun hash koodin() -menetelmää ei ohiteta, oletusmenetelmä Esine luokka kutsutaan. Tämä on natiivi menetelmä, mikä tarkoittaa, että se suoritetaan toisella kielellä, kuten C, ja palauttaa jonkin koodin objektin muistiosoitteesta. (Ei ole niin tärkeää tietää tarkalleen, miten tämä menetelmä toimii, ellet kirjoita JDK-koodia.)

 @HotSpotIntrinsicCandidate public native int hashCode (); 

Kun on yhtä suuri () ja hash koodin() menetelmiä ei ohiteta, näet sen sijaan yllä olevat menetelmät. Tässä tapauksessa menetelmät eivät täytä järjestelmän todellista tarkoitusta on yhtä suuri () ja hash koodin(), joka on tarkistaa, onko kahdella tai useammalla objektilla samat arvot.

Yleensä kun ohitat on yhtä suuri () sinun on myös ohitettava hash koodin().

Kohteiden vertaaminen yhtäläisiin ()

Käytämme on yhtä suuri () menetelmä Java-objektien vertaamiseksi. Voit selvittää, ovatko kaksi objektia samat, on yhtä suuri () vertaa objektien määritteiden arvoja:

 public class EqualsAndHashCodeExample {public static void main (String ... equalsExplanation) {System.out.println (uusi Simpson ("Homer", 35, 120) .equals (uusi Simpson ("Homer", 35, 120))); System.out.println (uusi Simpson ("Bart", 10, 120). On yhtä suuri (uusi Simpson ("El Barto", 10, 45))); System.out.println (uusi Simpson ("Lisa", 54, 60). Yhtäläiset (uusi objekti ())); } staattinen luokka Simpson {private String name; yksityinen ikä; yksityinen int-paino; public Simpson (Merkkijonon nimi, int-ikä, int-paino) {this.name = nimi; tämä. ikä = ikä; tämä.paino = paino; } @Override public boolean equals (Object o) {if (this == o) {return true; } if (o == null || getClass ()! = o.getClass ()) {return false; } Simpson simpson = (Simpson) o; paluuikä == simpson.age && weight == simpson.weight && name.equals (simpson.name); }}} 

Ensimmäisessä vertailussa on yhtä suuri () vertaa nykyistä objektin ilmentymää välitettyyn objektiin. Jos kahdella objektilla on samat arvot, on yhtä suuri () palaa totta.

Toisessa vertailussa on yhtä suuri ()tarkistaa, onko ohitettu objekti tyhjätai jos se on kirjoitettu eri luokkana. Jos kyseessä on eri luokka, objektit eivät ole samanarvoisia.

Lopuksi, on yhtä suuri () vertaa kohteiden kenttiä. Jos kahdella objektilla on samat kenttäarvot, objektit ovat samat.

Analysoidaan esineiden vertailuja

Katsotaan nyt näiden vertailujen tuloksia omassa main () menetelmä. Ensinnäkin verrataan kahta Simpson esineet:

 System.out.println (uusi Simpson ("Homer", 35, 120). On yhtä suuri (uusi Simpson ("Homer", 35, 120))); 

Kohteet ovat identtisiä, joten tulos on totta.

Seuraavaksi verrataan kahta Simpson esineet uudelleen:

 System.out.println (uusi Simpson("Bart", 10, 45). Yhtäläiset (uusi Simpson("El Barto", 10, 45)); 

Esineet ovat täällä lähes identtisiä, mutta niiden nimet ovat erilaiset: Bart ja El Barto. Siksi tulos on väärä.

Lopuksi verrataan a Simpson objekti ja luokan objektin esiintymä:

 System.out.println (uusi Simpson("Lisa", 54, 60). Yhtäläiset (uusi Esine())); 

Tässä tapauksessa tulos on väärä koska luokkatyypit ovat erilaisia.

on yhtä suuri () vs. ==

Ensi silmäyksellä == operaattori ja on yhtä suuri () menetelmä saattaa näyttää tekevän samaa, mutta todellisuudessa ne toimivat eri tavalla. == operaattori vertaa, osoittavatko kaksi objektiviittausta samaan objektiin. Esimerkiksi:

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

Ensimmäisessä vertailussa keksimme kaksi erilaista Simpson tapauksia, joissa käytetään Uusi operaattori. Tämän vuoksi muuttujat homer ja homer2 osoittaa eri Esine viittaukset muistipinoon. Joten meillä on väärä seurauksena.

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

Toisessa vertailussa ohitamme on yhtä suuri () menetelmä. Tässä tapauksessa vain nimiä verrataan. Koska molempien nimi Simpson Tulos on ”Homer” totta.

Kohteiden yksilöllinen tunnistaminen hashcodeilla ()

Käytämme hash koodin() menetelmä suorituskyvyn optimoimiseksi esineitä verrattaessa. Suoritetaanhash koodin() palauttaa yksilöllisen tunnuksen kullekin ohjelman kohteelle, mikä helpottaa kohteen koko tilan vertaamista huomattavasti.

Jos objektin hashcode ei ole sama kuin toisen kohteen hashcode, ei ole mitään syytä suorittaa on yhtä suuri () menetelmä: tiedät vain, että kaksi kohdetta eivät ole samat. Toisaalta, jos hashcode On sama, niin sinun on suoritettava on yhtä suuri () menetelmä sen määrittämiseksi, ovatko arvot ja kentät samat.

Tässä on käytännön esimerkki hash koodin().

 public class HashcodeConcept {public static void main (String ... hashcodeExample) {Simpson homer = uusi Simpson (1, "Homer"); Simpson bart = uusi Simpson (2, "Homer"); totuusarvo isHashcodeEquals = homer.hashCode () == bart.hashCode (); if (isHashcodeEquals) {System.out.println ("Pitäisi verrata myös yhtä suureen -menetelmään."); } else {System.out.println ("Ei pitäisi verrata yhtäläiseen -menetelmään, koska" + "id on erilainen, mikä tarkoittaa, että objektit eivät ole varmasti yhtä suuria."); }} staattinen luokka Simpson {int id; Merkkijono nimi; public Simpson (int id, String name) {this.id = id; tämä.nimi = nimi; } @Override public boolean equals (Object o) if (this == o) return true; if (o == null @Override public int hashCode () {return ID;}}} 

A hash koodin() joka palauttaa aina saman arvon, on kelvollinen, mutta ei kovin tehokas. Tässä tapauksessa vertailu palaa aina totta, joten on yhtä suuri () menetelmä suoritetaan aina. Tässä tapauksessa suorituskykyä ei paranneta.

Equals (): n ja hashcode: n () käyttäminen kokoelmien kanssa

Aseta käyttöliittymä on vastuussa siitä, ettei a Aseta alaluokka. Seuraavassa on joitain luokkia, jotka toteuttavat Aseta käyttöliittymä:

  • HashSet
  • Puujoukko
  • LinkedHashSet
  • CopyOnWriteArraySet

Vain ainutlaatuisia elementtejä voidaan lisätä a Aseta, joten jos haluat lisätä elementin HashSet luokassa (esimerkiksi), sinun on ensin käytettävä on yhtä suuri () ja hash koodin() menetelmiä sen varmistamiseksi, että elementti on ainutlaatuinen. Jos on yhtä suuri () ja hash koodin()menetelmiä ei ohitettu tässä tapauksessa, voit lisätä kaksoiskappaleita koodiin.

Käytämme alla olevaa koodia lisätä menetelmä lisätä uusi elementti a HashSet esine. Ennen uuden elementin lisäämistä HashSet tarkistaa, onko elementti jo olemassa annetussa kokoelmassa:

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

Jos objekti on sama, uutta elementtiä ei lisätä.

Hash-kokoelmat

Aseta ei ole ainoa kokoelma, jota käytetään on yhtä suuri () ja hash koodin(). HashMap, Hashtable ja LinkedHashMap edellyttävät myös näitä menetelmiä. Yleensä jos näet kokoelman, jonka etuliite on "Hash", voit olla varma, että se vaatii hash koodin() ja on yhtä suuri () menetelmiä, jotta niiden ominaisuudet toimisivat kunnolla.

Ohjeet yhtälöiden () ja hashcode () käyttämiseen

Suorita vain on yhtä suuri () menetelmä kohteille, joilla on sama yksilöllinen hashcode-tunnus. Sinun pitäisi ei suorittaa on yhtä suuri () kun hajautuskoodin tunnus on erilainen.

Taulukko 1. Hashcode-vertailut

Jos hash koodin() vertailu ...Sitten…
palauttaa arvon tosisuorittaa on yhtä suuri ()
palauttaa arvon falseälä suorita on yhtä suuri ()

Tätä periaatetta käytetään pääasiassa Aseta tai Hash kokoelmia suorituskyvyn vuoksi.

Kohteiden vertailun säännöt

Kun hash koodin() vertailu palauttaa väärä, on yhtä suuri () menetelmä on palautettava myös väärä. Jos hajautuskoodi on erilainen, objektit eivät todellakaan ole samanlaisia.

Taulukko 2. Kohteiden vertailu hajakoodiin ()

Kun hashcode-vertailu palaa ... on yhtä suuri () menetelmän pitäisi palata ...
tottatotta vai tarua
vääräväärä

Kun on yhtä suuri () method palaa totta, se tarkoittaa, että objektit ovat samat kaikissa arvoissa ja määritteissä. Tässä tapauksessa myös hashcode-vertailun on oltava totta.

Taulukko 3. Kohteiden vertailu yhtä suureen ()

Kun on yhtä suuri () menetelmä palauttaa ... hash koodin() menetelmän pitäisi palata ...
tottatotta
väärätotta vai tarua

Ota yhtälö () ja hashcode () haaste!

On aika testata taitojasi on yhtä suuri () ja hash koodin() menetelmiä. Tavoitteesi tässä haasteessa on selvittää näiden kahden tulos on yhtä suuri () - menetelmien vertailut ja arvaa Aseta kokoelma.

Aloita tutkimalla seuraavaa koodia huolellisesti:

 public class EqualsHashCodeChallenge {public static void main (String ... doYourBest) {System.out.println (uusi Simpson ("Bart"). on yhtä suuri (uusi Simpson ("Bart"))); Simpson overriddenHomer = uusi Simpson ("Homer") {public int hashCode () {return (43 + 777) + 1; }}; System.out.println (uusi Simpson ("Homer"). On yhtä suuri (overriddenHomer)); Set set = new HashSet (Set.of (uusi Simpson ("Homer"), uusi Simpson ("Marge"))); set.add (uusi Simpson ("Homer")); set.add (ohitettuHomer); System.out.println (set.size ()); } staattinen luokka Simpson {String name; Simpson (merkkijono) {this.name = nimi; } @Override public boolean equals (Object obj) {Simpson otherSimpson = (Simpson) obj; palauta this.name.equals (otherSimpson.name) && this.hashCode () == otherSimpson.hashCode (); } @Override public int hashCode () {return (43 + 777); }}} 

Muista, analysoi ensin koodi, arvaa tulos, ja suorita sitten koodi. Tavoitteenasi on parantaa taitojasi koodianalyysillä ja hyödyntää Java-ydinkäsitteitä, jotta koodistasi tulee tehokkaampi. Valitse vastauksesi ennen oikean vastauksen tarkistamista.

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

Mitä juuri tapahtui? Ymmärrä yhtälöt () ja hashcode ()

Ensimmäisessä on yhtä suuri () menetelmän vertailu, tulos on totta koska objektin tila on täsmälleen sama ja hash koodin() method palauttaa saman arvon molemmille kohteille.

Toisessa on yhtä suuri () menetelmien vertailu, hash koodin() menetelmä ohitetaan syrjäyttää Homer muuttuja. Nimi on “Homer” molemmille Simpson esineitä, mutta hash koodin() method palauttaa eri arvon kohteelle ohitettu Homer. Tässä tapauksessa lopullinen tulos on yhtä suuri () menetelmä on väärä koska menetelmä sisältää vertailun hajautuskoodiin.

Saatat huomata, että kokoelman koko on asetettu pitämään kolme Simpson esineitä. Tarkistetaan tämä yksityiskohtaisesti.

Sarjan ensimmäinen objekti lisätään normaalisti:

 uusi Simpson ("Homer"); 

Myös seuraava objekti lisätään normaalisti, koska sillä on erilainen arvo kuin edellisellä objektilla:

 uusi Simpson ("Marge"); 

Lopuksi seuraava Simpson objektilla on sama arvo kuin ensimmäisellä objektilla. Tässä tapauksessa objektia ei lisätä:

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

Kuten tiedämme, syrjäyttää Homer objekti käyttää eri hashcode-arvoa kuin normaali Simpson (“Homer”) instantiointi. Tästä syystä tämä elementti lisätään kokoelmaan:

 ohitettu Homer; 

Vastausavain

Vastaus tähän Java-haastajaan on B. Tuotos olisi:

 tosi väärä 3 

Video-haaste! Virheenkorjaus on yhtä suuri () ja hashcode ()

Virheenkorjaus on yksi helpoimmista tavoista hyödyntää ohjelmointikonsepteja täysin ja parantaa samalla koodiasi. Tässä videossa voit seurata mukana, kun minä virheenkorjaan ja selitän Java on yhtä suuri () ja hash koodin() haaste.

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