Koks skirtumas tarp „HashMap“ ir „Map“ Java?

Koks skirtumas tarp šių kortelių, kurias sukūriau (kitame klausime, žmonės atsakė, naudodamiesi jais, atrodo, pakaitomis, ir man įdomu, ar jie skiriasi):

 HashMap<String, Object> map = new HashMap<String, Object>(); Map<String, Object> map = new HashMap<String, Object>(); 
298
28 авг. Tony Stark rinkinys 28 d. 2009-08-28 19:46 '09, 19:46 PM 2009-08-28 19:46
@ 13 atsakymų

Nėra skirtumo tarp objektų; abiem atvejais turite HashMap<String, Object> . Sąsajoje, kurią turite, yra skirtumas. Pirmuoju atveju sąsaja HashMap<String, Object> ir antroje - Map<String, Object> . Tačiau pagrindinis tikslas yra tas pats.

Naudojant „ Map<String, Object> “, privalumas yra tas, kad galite pakeisti bazinį objektą į kitą žemėlapio tipą, nesilaikant sutarties su bet kuriuo kodu, kuris jį naudoja. Jei ją paskelbiate kaip „ HashMap<String, Object> , turite pakeisti savo sutartį, jei norite pakeisti bazės įgyvendinimą.


Pavyzdys: tarkime, kad rašau šią klasę:

 class Foo { private HashMap<String, Object> things; private HashMap<String, Object> moreThings; protected HashMap<String, Object> getThings() { return this.things; } protected HashMap<String, Object> getMoreThings() { return this.moreThings; } public Foo() { this.things = new HashMap<String, Object>(); this.moreThings = new HashMap<String, Object>(); } // ...more... } 

Klasėje yra keletas eilutės eilutės elementų, kuriuos jis dalijasi (per prieigos metodus) su poklasiais. Tarkime, aš parašau jį su HashMap pradžia, nes manau, kad rašant klasę reikia naudoti tinkamą struktūrą.

Vėliau Marija parašo kodą. Ji turi kažką, ką ji turi susieti su abiem things ir moreThings , todėl, žinoma, ji ją pateikia įprasto metodo, ir ji naudoja tą patį tipą, kurį naudodavau getThings / getMoreThings apibrėžiant savo metodą:

 class SpecialFoo extends Foo { private void doSomething(HashMap<String, Object> t) { // ... } public void whatever() { this.doSomething(this.getThings()); this.doSomething(this.getMoreThings()); } // ...more... } 

Vėliau aš nusprendžiau, kad faktiškai geriau naudoti „ TreeMap vietoj „ HashMap “. Aš atnaujinu „ Foo , pakeisdamas „ HashMap į „ TreeMap . Dabar „ SpecialFoo nebėra kompiliuojama, nes nutraukiau sutartį: „ Foo sakė, kad ji suteikė „ HashMap , bet dabar ji suteikia „ TreeMaps . Taigi dabar turime nustatyti SpecialFoo (ir šis vaizdas gali pulsuoti per kodo bazę).

Jei turėjau tikrai gerą priežastį pasidalyti savo įgyvendinimu naudojant „ HashMap (ir tai tiesa), tai, ką turėjau padaryti, buvo getThings ir getMoreThings , kurias grąžino Map<String, Object> , o ne konkretesnis. Iš tikrųjų, išskyrus rimtų priežasčių, kodėl darote kažką kitą, netgi Foo viduje, turbūt turėčiau paskelbti things ir moreThings kaip Map , o ne HashMap / TreeMap :

 class Foo { private Map<String, Object> things; // <== Changed private Map<String, Object> moreThings; // <== Changed protected Map<String, Object> getThings() { // <== Changed return this.things; } protected Map<String, Object> getMoreThings() { // <== Changed return this.moreThings; } public Foo() { this.things = new HashMap<String, Object>(); this.moreThings = new HashMap<String, Object>(); } // ...more... } 

Atkreipkite dėmesį, kaip dabar naudoju Map<String, Object> kur tik galiu, tik būdamas konkretus, kai kuriu faktinius objektus.

Jei padariau, Marija tai padarys:

 class SpecialFoo extends Foo { private void doSomething(Map<String, Object> t) { // <== Changed // ... } public void whatever() { this.doSomething(this.getThings()); this.doSomething(this.getMoreThings()); } } 

... ir „ Foo keitimas nepadarytų „ SpecialFoo nutraukimo.

Sąsajos (ir bazinės klasės) leidžia mums atskleisti tik tiek, kiek reikia, išlaikant lankstumą po viršeliais, kad galėtume atlikti atitinkamus pakeitimus. Apskritai norime, kad mūsų nuorodos būtų kuo paprastesnės. Jei mums nereikia žinoti šio „ HashMap , tiesiog jį vadinkite.

Tai nėra aklas, bet apskritai kodavimas į labiausiai bendrąją sąsają bus mažiau trapus nei kodavimas į kažką konkretesnio. Jei tai prisimenu, aš nebūtų sukūręs „ Foo , kuris įsteigė Mariją dėl „ SpecialFoo nesėkmės. Jei Marija tai prisimintų, tada, nors aš sugadinau „ Foo , ji paskelbė savo asmeninį Map metodą vietoj „ HashMap , o mano besikeičianti „ Foo sutartis neturės įtakos jos kodui.

Kartais tai negalite padaryti, kartais jums reikia būti konkrečiais. Bet jei neturite pagrindo, supainiokite su mažiausiai specifine sąsaja.

359
28 авг. atsakymas, kurį pateikė TJ Crowder 28 rug. 2009-08-28 19:50 '09, 07:50 pm 2009-08-28 19:50

Žemėlapis yra „ HashMap“ įdiegta sąsaja. Skirtumas yra tas, kad antrojo įgyvendinimo metu jūsų nuoroda į „HashMap“ leis naudoti žemėlapio sąsajoje apibrėžtas funkcijas, o pirmoji leis jums naudoti visas viešai prieinamas funkcijas „HashMap“ (įskaitant žemėlapio sąsają).

Tikriausiai bus tikslinga perskaityti „Sun“ sąsajos pamoką.

52
28 авг. Atsakymą pateikia „ Graphics Noob“ 28 rug. 2009-08-28 19:53 '09, 19:53, 2009-08-28 19:53

Aš tik ketinau tai padaryti kaip priimtą atsakymą komentuodamas, bet jis pernelyg išsigandęs (nekenčiu, kad neturiu eilutės pertraukų)

ah, taigi skirtumas yra tas, kad apskritai žemėlapis turi tam tikrus metodus, susijusius su juo. tačiau yra įvairių būdų arba sukurti žemėlapį, pvz., „HashMap“, ir šie skirtingi būdai suteikia unikalius metodus, kurių ne visi žemėlapiai.

Tiksliai - ir jūs visada norite naudoti dažniausiai naudojamą sąsają. Apsvarstykite „ArrayList“ ir „LinkedList“. Didelis skirtumas yra, kaip jais naudojate, bet jei naudojate „Sąrašą“, galite lengvai persijungti tarp jų.

Tiesą sakant, galite pakeisti dešinę iniciatoriaus pusę dinamiškesne instrukcija. kaip kažkas panašaus:

 List collection; if(keepSorted) collection=new LinkedList(); else collection=new ArrayList(); 

Taigi, jei ketinate užpildyti rinkinį su įterpimo rūšimi, turite naudoti susietą sąrašą (įterpti į masyvų sąrašą įterpimas yra nusikalstamas.) Bet jei jums nereikia surūšiuoti ir tiesiog pridėti, naudokite „ArrayList“ (efektyviau kitoms operacijoms).

Tai yra gana didelis plotas, nes kolekcijos nėra geriausias pavyzdys, tačiau OO dizaine viena iš svarbiausių sąvokų yra naudoti fasado sąsają, kad galėtumėte pasiekti įvairius objektus su tuo pačiu kodu.

Redaguoti atsakymą į komentarą:

Kalbant apie komentarą žemiau esančiame žemėlapyje, „Taip“, naudojant „Žemėlapio“ sąsają, jūs apribojate tik šiuos metodus, nebent atsisakote rinkinio iš žemėlapio į „HashMap“ (kuris visiškai TOLIS nugalėjo tikslą).

Dažnai tai, ką darysite, yra sukurti objektą ir užpildyti jį tam tikru tipu („HashMap“), tam tikru būdu „sukurti“ arba „inicijuoti“, tačiau šis metodas grąžins „žemėlapį“, kurio nereikia manipuliuoti. kaip hashmap.

Jei kada nors reikia išeiti, galite naudoti netinkamą sąsają arba jūsų kodas nėra gerai struktūrizuotas. Atkreipkite dėmesį, kad leidžiama, kad viena jūsų kodo dalis būtų traktuojama kaip „HashMap“, o kita - tai „žemėlapis“, tačiau tai turėtų įvykti „žemyn“. taigi jūs niekada nenustosite.

Taip pat atkreipkite dėmesį į pusiau aštrius rodinius, nurodytus sąsajose. „LinkedList“ sukuria gerą kaminą ar eilę, „ArrayList“ sukuria gerą kaminą, bet baisią eilę (vėl ištrynus visą sąrašą), todėl „LinkedList“ įgyvendina eilės sąsają, „ArrayList“ nėra.

17
28 авг. Bill K 28 d. atsakymas . 2009-08-28 20:16 '09 ne 20:16 2009-08-28 20:16

2019

16
16 февр. atsakymas pateikiamas atish shimpi 16 vas. 2015-02-16 13:06 '15, 13:06 2015-02-16 13:06

Kaip pažymėjo TJ Crowder ir Adamski, viena sąsaja skirta sąsajai, o kita - konkrečiam sąsajos diegimui. Joshua Block teigimu, visada turėtumėte pabandyti koduoti sąsajas, kad galėtumėte geriau tvarkyti bazės diegimo pokyčius - tai yra, jei „HashMap“ netikėtai neatitinka jūsų sprendimo ir jums reikia pakeisti žemėlapio įgyvendinimą, vis tiek galite naudoti žemėlapio sąsają ir pakeisti kūrimo pavyzdžio tipą.

12
28 авг. atsakymas pateikiamas aperkins 28 rug . 2009-08-28 19:53 '09, 19:53, 2009-08-28 19:53

Antrajame pavyzdyje nuoroda „žemėlapis“ yra „Map“ tipo, kuris yra „ HashMap (ir kitų tipų Map ) įdiegta sąsaja. Ši sąsaja yra sutartis, kurioje teigiama, kad objektas atitinka raktus su vertybėmis ir palaiko įvairias operacijas (pvz., put , get ). Nėra nieko apie Map įgyvendinimą (šiuo atveju „ HashMap ).

Antrasis metodas paprastai yra pageidautinas, nes paprastai nenorite atskleisti konkretaus žemėlapio įgyvendinimo metodais, naudojant Map arba API apibrėžimą.

8
28 авг. atsakymą pateikė Adamski 28 rug. 2009-08-28 19:51 '09 19:51 2009-08-28 19:51

Žemėlapis yra statinis žemėlapio tipas , o „HashMap“ yra dinamiškas tipas . Tai reiškia, kad kompiliatorius apdoros jūsų žemėlapio objektą kaip vieną iš žemėlapių tipų, nors vykdymo metu jis gali nukreipti į bet kurį potipį.

Ši programavimo praktika, palyginti su sąsajomis, o ne įgyvendinimu, turi papildomą pranašumą: ji gali, pavyzdžiui, pakeisti dinaminį žemėlapio tipą vykdymo metu, jei tai yra žemėlapio potipis (pvz., „LinkedHashMap“) ir keisti žemėlapio elgseną skrydžio metu.

Gera nykščio taisyklė yra kuo mažiau abstrakta API lygmeniu: jei, pvz., Programavimo būdas yra dirbti su žemėlapiais, reikia tiesiog nurodyti parametrą kaip žemėlapį, o ne griežtesnę (nes mažiau abstrakčią) tipą HashMap. Taigi, jūsų API vartotojas gali būti lankstus, atsižvelgiant į tai, kokį žemėlapio įgyvendinimą jie nori perkelti į jūsų metodą.

8
28 авг. atsakymą pateikė Matthias 28 rug. 2009-08-28 20:03 '09, 20:03 2009-08-28 20:03

Jūs sukuriate tas pačias korteles.

Bet jūs galite užpildyti skirtumą, kai jį naudojate. Pirmuoju atveju galite naudoti specialius „HashMap“ metodus (bet nepamenu, kad kas nors iš tikrųjų būtų naudinga), ir jūs galite jį perduoti kaip „HashMap“ parametrą:

 public void foo (HashMap<String, Object) { ... } ... HashMap<String, Object> m1 = ...; Map<String, Object> m2 = ...; foo (m1); foo ((HashMap<String, Object>)m2); 
3
28 авг. atsakymas pateikiamas romėnų 28 rug. 2009-08-28 19:50 '09, 07:50 pm 2009-08-28 19:50

Balsavo už viršutinį atsakymą, ir daugelis iš jų pirmiau pabrėžia „bendresnį, geresnį“, norėčiau iškasti šiek tiek daugiau.

Map yra struktūrinė sutartis, o „ HashMap yra įgyvendinimas, kuris pateikia savo metodus įvairioms realaus pasaulio problemoms spręsti: kaip apskaičiuoti indeksą, koks yra pajėgumas ir kaip jį padidinti, kaip ją įterpti, kaip įrašyti unikalų indeksą ir pan.

Peržiūrėti šaltinio kodą:

Žemėlapyje yra metodas, containsKey(Object key) :

 boolean containsKey(Object key); 

„JavaDoc“:

boolean java.util.Map.containsValue (objekto vertė)

Grąžinamas tiesa, jei šis ekranas parodo vieną ar daugiau raktų į nurodytą vertę. Formaliau grąžinamas tik tada ir tik tuo atveju, jei šis žemėlapis turi bent vieną vertę v reikšme tokiu būdu (value==null ? v==null : value.equals(v)) . Ši operacija greičiausiai užtruks laiko liniją, skirtą žemėlapio dydžiui daugelyje žemėlapio sąsajos realizacijų.

Parametrai: vertė

kurių buvimas šioje kortelėje turi būti nurodytas

Grąžina: tiesa

jei šis atvaizdavimas parodo vieną ar daugiau nustatytų raktų

valueThrows:

„ClassCastException“ - jei reikšmė šiam žemėlapiui yra netinkama (neprivaloma)

„NullPointerException“ - jei nurodyta vertė yra nulinė, ir šis žemėlapis neleidžia nulinės vertės (pasirinktinai)

Jis reikalauja, kad jo įgyvendinimas tai padarytų, bet „kaip“ yra jo laisve, tik siekiant užtikrinti, kad jis sugrįžtų teisingai.

HashMap :

 public boolean containsKey(Object key) { return getNode(hash(key), key) != null; } 

Pasirodo, kad HashMap naudoja hashcode, kad patikrintų, ar ši kortelė turi raktą. Taigi, jis turi pranašumą, kad jis yra maišymo algoritmas.

2
28 сент. atsakymą pateikė „ WesternGun “ 28 sep . 2017-09-28 11:00 '17, 11:00 2017-09-28 11:00

Žemėlapis yra sąsaja, ir Hashmap yra klasė, kuri ją įgyvendina.

Taigi, įgyvendindami tuos pačius objektus.

1
28 авг. Atsakymą pateikė Diego Dias 28 rug. 2009-08-28 19:52 '09 19:52 val. 2009-08-28 19:52

Žemėlapis yra sąsaja, ir Hashmap yra klasė, kuri įgyvendina žemėlapio sąsają.

1
09 мая '17 в 9:24 2017-05-09 09:24 atsakymą pateikė user6623857 gegužės 09 '17, 09:24 2017-05-05 09:24

„HashMap“ yra žemėlapio įgyvendinimas, todėl jis yra lygiai toks pats, tačiau jis turi „klono ()“ metodą, kaip matau nuorodos vadove))

0
23 сент. kolyaseg atsakymas, rugsėjo 23 d 2014-09-23 15:49 '14 at 15:49 2014-09-23 15:49
 HashMap<String, Object> map1 = new HashMap<String, Object>(); Map<String, Object> map2 = new HashMap<String, Object>(); 

Visų pirma, Map yra sąsaja, turinti skirtingą įgyvendinimą, pavyzdžiui, „ HashMap , „ TreeHashMap , „ LinkedHashMap ir kt. Sąsaja veikia kaip klasė, skirta diegimo klasei. Taigi, pagal OOP taisyklę, bet kuri konkreti klasė, įgyvendinanti Map taip pat yra Map . Tai reiškia, kad galime priskirti / įdėti bet kokį „ HashMap tipo kintamąjį į „ Map tipo kintamąjį be jokio tipo liejimo.

Tokiu atveju galime priskirti map1 map2 be liejimo ar duomenų praradimo -

 map2 = map1 
0
09 февр. Atsakymas duotas Razibo vasario 09 d. 2015-02-09 22:10 '15, 10:10 pm 2015-02-09 22:10

Kiti klausimai apie „ „Klausimas“