Programavimas

„Hashtables“

2002 m. Birželio 21 d

Klausimas: Kai naudoju objektą kaip raktą „Hashtable“, ką turiu perrašyti objekto klasėje ir kodėl?

A: Kai kuriate savo pagrindinį objektą, skirtą naudoti a „Hashtable“, turite nepaisyti Object.equals () ir Object.hashCode () metodai nuo „Hashtable“ naudoja raktų derinį hashCode () ir lygi () būdai, kaip greitai išsaugoti ir gauti jo įrašus. Tai taip pat yra bendra taisyklė, kurią jūs nepaisote lygi (), jūs visada nepaisote hashCode ().

Daugiau apie tai

Šiek tiek išsamesnis paaiškinimas padės jums suprasti „Hashtable“saugojimo ir paieškos mechanizmas. A „Hashtable“ viduje yra grupių, kuriose jis saugo raktų / reikšmių poras. „Hashtable“ naudoja rakto maišos kodą, kad nustatytų, kurioje grupėje raktų / reikšmių pora turėtų susieti.

1 paveiksle parodyta a „Hashtable“ ir jo kibirai. Kai perduodate raktą / vertę „Hashtable“, jis klausia rakto maišos kodo. „Hashtable“ naudoja tą kodą norėdamas nustatyti raktą / vertę. Pavyzdžiui, jei maišos kodas lygus nuliui, „Hashtable“ įterpia vertę į grupę 0. Panašiai, jei maišos kodas yra du, „Hashtable“ įterpia vertę į 2 grupę. (Tai yra supaprastintas pavyzdys; „Hashtable“ pirmiausia masažuos maišos kodą, taigi „Hashtable“ nemėgina įterpti vertės už grupės ribų.)

Tokiu būdu naudojant maišos kodą, „Hashtable“ taip pat gali greitai nustatyti, kuriame segmente ji įdėjo vertę, kai bandote ją nuskaityti.

„Hashcodes“ rodo tik pusę paveikslo. Maišos kodas nurodo tik „Hashtable“ į kurį segmentą mesti raktą / vertę. Tačiau kartais keli objektai gali susieti su tuo pačiu segmentu, įvykiu, vadinamu a susidūrimas. Java kalboje „Hashtable“ reaguoja į susidūrimą įdėdamas kelias vertes į tą patį segmentą (kiti diegimai gali susidoroti su susidūrimais skirtingai). 2 paveiksle parodyta, kas a „Hashtable“ gali atrodyti po kelių susidūrimų.

Dabar įsivaizduokite, kad paskambinsite gauti () klavišu, susietu su kibiru 0. The „Hashtable“ dabar reikės atlikti nuoseklų paiešką naudojant raktų / reikšmių poras 0 grupėje, kad surastumėte jūsų prašomą vertę. Norėdami atlikti šią paiešką, „Hashtable“ atlieka šiuos veiksmus:

  1. Užklausa rakto maišos kodą
  2. Gaukite raktų / reikšmių, esančių grupėje, sąrašą, kurį suteikia maišos kodas
  3. Nuskaitykite kiekvieną įrašą nuosekliai, kol bus perduotas raktas, kuris yra lygus raktui gauti () yra rastas

Ilgas atsakymas į trumpą klausimą, kurį žinau, bet jis dar blogėja. Tinkamai viršesnis lygi () ir hashCode () yra nereikšmingas pratimas. Turite būti labai atsargūs, kad garantuotumėte abiejų būdų sutartis.

Įgyvendinant lygu ()

Pagal lygi () „Javadoc“, metodas turi atitikti šias taisykles:

" lygi () metodas įgyvendina ekvivalentiškumo santykį:
  • Jis yra refleksinis: bet kuriai pamatinei vertei x x. lygi (x) turėtų grįžti tiesa
  • Tai simetriška: Bet kurioms pamatinėms reikšmėms x ir y x. lygi (y) turėtų grįžti tiesa tada ir tik tada y. lygi (x) grįžta tiesa
  • Jis yra tranzityvus: Bet kurioms pamatinėms reikšmėms x, y ir z, jei x. lygi (y) grįžta tiesa ir y. lygi (z) tada grįžta tiesa x. lygi (z) turėtų grįžti tiesa
  • Jis yra nuoseklus: bet kurioms pamatinėms reikšmėms x ir y reikia keleto pakvietimų x. lygi (y) nuosekliai grąžinti teisingą arba nuolat grąžinti klaidingą, jei nėra pakeista jokia informacija, naudojama lygiaverčiams objekto palyginimams
  • Bet kuriai nulio nulinei pamatinei vertei x, x. lygi (nulinė) turėtų grąžinti klaidingą "

Į Efektyvi „Java“, Joshua Blochas siūlo penkių žingsnių receptą, kaip parašyti efektingą lygi () metodas. Štai receptas kodo forma:

viešoji klasė EffectiveEquals {private int valueA; privati ​​int vertėB; . . . viešoji loginė reikšmė lygi (Object o) {if (this == o) {// 1 veiksmas: atlikite == test return return true; } if (! („EffectiveEquals“ egzempliorius)) {// 2 žingsnis: tikrinimo egzempliorius return false; } Efektyvioji lygybė ee = (Efektyvioji lygybė) o; // 3 veiksmas: „Cast“ argumentas // 4 veiksmas: patikrinkite, ar kiekviename svarbiame lauke jie yra lygūs. pirma grąža ee.valueA == valueA && ee.valueB == valueB; }. . . } 

Pastaba: Nuo to laiko nereikia atlikti niekinio patikrinimo nulinis „EffectiveEquals“ egzempliorius įvertins klaidingai.

Galiausiai, atlikdami 5 veiksmą, grįžkite į lygi ()sutartį ir paklauskite savęs, ar lygi () metodas yra refleksinis, simetriškas ir tranzityvus. Jei ne, pataisykite!

Diegiant hashCode ()

Dėl hashCode ()„Javadoc“ bendra sutartis sako:

  • "Visada, kai vykdant" Java "programą ji yra naudojama tam pačiam objektui daugiau nei vieną kartą, hashCode () metodas turi nuosekliai pateikti tą patį sveikąjį skaičių, jei nėra modifikuota lygiomis objekto palyginimais naudojama informacija. Šis sveikasis skaičius neturi išlikti nuoseklus nuo vieno programos vykdymo iki kito tos pačios programos vykdymo.
  • Jei du objektai yra lygūs pagal lygus (objektas) metodą, tada paskambinę hashCode () metodas kiekvienam iš dviejų objektų turi sudaryti tą patį sveiko skaičiaus rezultatą.
  • Nereikalaujama, kad jei du objektai yra nelygūs pagal lygu (java.lang.Object metodą, tada paskambinę hashCode () metodas kiekvienam iš dviejų objektų turi pateikti skirtingus sveiko skaičiaus rezultatus. Tačiau programuotojas turėtų žinoti, kad pateikiant skirtingus sveikojo skaičiaus rezultatus nevienodiems objektams, gali pagerėti grotelių našumas. "

Tinkamai veikiančio darbo sukūrimas hashCode () metodas yra sunkus; dar sunkiau, jei nagrinėjamas objektas nėra nekintamas. Nurodytam objektui maišos kodą galite apskaičiuoti įvairiais būdais. Veiksmingiausias metodas grindžia skaičių pagal objekto laukus. Be to, šias vertybes galite derinti įvairiais būdais. Štai du populiarūs metodai:

  • Galite objekto laukus paversti eilute, susieti eilutes ir grąžinti gautą maišos kodą
  • Galite pridėti kiekvieno lauko maišos kodą ir grąžinti rezultatą

Nors egzistuoja ir kiti, išsamesni metodai, du minėti metodai yra lengviausiai suprantami ir įgyvendinami.

Tony Sintesas yra nepriklausomas konsultantas ir „First Class Consulting“, konsultacinės firmos, kuri specializuojasi sujungiant skirtingas įmonių sistemas ir mokymus, įkūrėjas. Už „First Class Consulting“ ribų Tony yra aktyvus laisvai samdomas rašytojas, taip pat knygos „Sams išmokyk save į objektą orientuoto programavimo per 21 dieną“ autorius (Sams, 2001; ISBN: 0672321092).

Sužinokite daugiau apie šią temą

  • Jei norite sužinoti „Hashtable Javadoc“, eikite į

    //java.sun.com/j2se/1.4/docs/api/java/util/Hashtable.html

  • Vipano Singlos „Equals () ir hashCode () įgyvendinimas“ pateikia išsamią diskusiją apie lygių () ir hashCode () metodų nepaisymą.

    //www.vipan.com/htdocs/hashcode_help.html

  • Objektas.lygus () Javadokas

    //java.sun.com/j2se/1.4/docs/api/java/lang/Object.html#equals(java.lang.Object)

  • „Object.hashCode“ () „Javadoc“

    //java.sun.com/j2se/1.4/docs/api/java/lang/Object.html#hashCode ()

  • Joshua Blochui Efektyvus „Java“ programavimo kalbos vadovas (Addison Wesley Professional, 2001; ISBN0201310058), eikite į

    //www.amazon.com/exec/obidos/ASIN/0201310058/javaworld

  • Norėdami gauti daugiau straipsnių apie „Java“ klases ir metodus, naršykite API skyrius „JavaWorld“s aktuali rodyklė

    //www.javaworld.com/channel_content/jw-apis-index.shtml

  • Norite daugiau? Žr „Java“ klausimai ir atsakymai viso klausimų ir atsakymų katalogo rodyklės puslapis

    //www.javaworld.com/columns/jw-qna-index.shtml

  • Norėdami gauti daugiau nei 100 įžvalgių „Java“ patarimų iš geriausių verslo atstovų, apsilankykite „JavaWorld“s „Java“ patarimai rodyklės puslapis

    //www.javaworld.com/columns/jw-tips-index.shtml

  • Sužinokite „Java“ pagrindus mūsų „Java“ pradedantysis diskusija

    //forums.idg.net/[email protected]@.ee6b804

  • Prisiregistruokite „JavaWorld“nemokamai kas savaitę „Core Java“ pašto naujienlaiškis

    //www.javaworld.com/subscribe

  • Rasite daugybę su IT susijusių straipsnių iš mūsų seserų leidinių .net

Šią istoriją „Hashtables“ iš pradžių išleido „JavaWorld“.