Re: Proč není genericita v metodách Map jako get(), remove()?
Ahojte, 2011/4/13 Libor Jelinek ljeli...@virtage.com: Studuju collection framework a mám k otázku rozhraní Map. To má uvedeno, že je to pár key-value K, V. .. Proč tedy metoda jako containsKey() je deklarována jako containsKey(Object key) a nikoli containsKey(K key)? Dále např. proč je V get(Object key) a nikoli V get(K key)? Poč je V remove(Object key) a nikoli V remove(K key)? Copy/paste ze stackoverflow (http://stackoverflow.com/questions/857420/what-are-the-reasons-why-map-getobject-key-is-not-fully-generic): As mentioned by people above, the reason why get(), etc. is not generic because the key of the entry you are retrieving does not have to be the same type as the object that you pass in to get(); the specification of the method only requires that they be equal. This follows from how the equals() method takes in an Object as parameter, not just the same type as the object. Although it may be commonly true that many classes have equals() defined so that its objects can only be equal to objects of its own class, there are many places in Java where this is not the case. For example, the specification for List.equals() says that two List objects are equal if they are both Lists and have the same contents, even if they are different implementations of List. So coming back to the example in this question, according to the specification of the method is possible to have a MapArrayList, Something and for me to call get() with a LinkedList as argument, and it should retrieve the key which is a list with the same contents. This would not be possible if get() were generic and restricted its argument type. Díky Libor -- pepa cacek
Re: Proč není genericita v metodách Map jako get(), remove()?
Zdravím, našel jsem celkem rozumné vysvětlení: Restrikce se zavádějí proto, aby se něco nepokazilo. Zavoláním get s jiným typem se nic nepokazí. Ještě trošku umělý příklad: MapString,Date datumyNarozeni = ... class Person { String fullName String login hashCode { return login.hashCode(); } equals(Object o) { return login.equals(o); } } datumyNarozeni.put(michal,new Date()); odnekud mi prijde objekt Person p kde je login michal, pak muzu udelat: datumyNarozeni.get(p) a dostanu to spravne datum Martin Dne 13.4.2011 07:44, Libor Jelinek napsal(a): Dobrý den! Studuju collection framework a mám k otázku rozhraní Map. To má uvedeno, že je to pár key-value K, V. /java.util Interface MapK,V Type Parameters:K - the type of keys maintained by this mapV - the type of mapped values/ Proč tedy metoda jako *containsKey()* je deklarována jako *containsKey(Object key)* a nikoli *containsKey(K key)*? Dále např. proč je *V get(Object key)* a nikoli *V get(K key)*? Poč je *V remove(Object key)* a nikoli *V remove(K key)*? A to i v JDK7 - tedy dávno dávno po zavedení genericity. Možná to mi něco nedochází jako začátečníkovi, ale pak mě to vrací k beztypovým kolekcím z JDK4 a umožňuje pěkné čunárničky jako, že místo type error dostanu jen null když jako jako klíč jasně označený v deklaraci jako Integer můžu používat klidně String, Float, ale i ZipEntry - zkrátka potomek Object, tedy cokoli: import java.util.*; public class MapPokus1 { public static void main(String[] args) { HashMapInteger, String psc = new HashMapInteger, String(); psc.put(12000, Praha 1); psc.put(28101, Velim); System.out.println(psc.get(28101));// Velim System.out.println(psc.get(28101));// Velim System.out.println(psc.get(28101));// žádná chyba jen null !!! System.out.println(psc.get(3.14));// žádná chyba jen null !!! System.out.println(psc.get(new ZipEntry(soub.txt) )); // žádná chyba jen null !!! } } Díky Libor -- Martin Beránek ICZ a.s., Pobočka Brno smime.p7s Description: S/MIME Cryptographic Signature
Re: Proč není genericita v metodách Map jako get(), remove()?
2011/4/13 Martin Beránek martin.bera...@i.cz: Zdravím, našel jsem celkem rozumné vysvětlení: Restrikce se zavádějí proto, aby se něco nepokazilo. Zavoláním get s jiným typem se nic nepokazí. Ještě trošku umělý příklad: MapString,Date datumyNarozeni = ... class Person { String fullName String login hashCode { return login.hashCode(); } equals(Object o) { return login.equals(o); } } datumyNarozeni.put(michal,new Date()); odnekud mi prijde objekt Person p kde je login michal, pak muzu udelat: datumyNarozeni.get(p) a dostanu to spravne datum Martin tak tento příklad se mi hodně nelíbí. Takového programátora zatahat za uši ;-) Nebudu koukat do implementace Person, jak je napsaný hashCode a equals ... Určitě by každý normální programátor napsal toto: datumyNarozeni.get(p.getLogin()); V každém případě - původní dotaz je docela namístě. Úryvek ze stackoverflow mě úplně nepřesvědčil ... Kdyby člověk použil MapList, Something místo MapArrayList, Something, tak by to fungovalo i s ArrayList i s LinkedList. Fafi
Re: Proč není genericita v metodách Map jako get(), remove()?
Dobrý den. Myslím si, že datumyNarozeni.get(p.getLogin()); by nešlo použít, pokud by byl klíč složený z více položek. Pokud by objekt Person měl např. string name a string surname, nebo by došlo následně k dalšímu rozšíření - např. o rok narození, stačilo by myslím pouze náležitě změnit hash a equals a vše by pořád fungovalo. Původní zpráva Od: Ondřej Fafejta fafejta.ond...@gmail.com Předmět: Re: Proč není genericita v metodách Map jako get(), remove()? Datum: 13.4.2011 08:38:05 2011/4/13 Martin Beránek martin.bera...@i.cz: Zdravím, našel jsem celkem rozumné vysvětlení: Restrikce se zavádějí proto, aby se něco nepokazilo. Zavoláním get s jiným typem se nic nepokazí. Ještě trošku umělý příklad: MapString,Date datumyNarozeni = ... class Person { String fullName String login hashCode { return login.hashCode(); } equals(Object o) { return login.equals(o); } } datumyNarozeni.put(michal,new Date()); odnekud mi prijde objekt Person p kde je login michal, pak muzu udelat: datumyNarozeni.get(p) a dostanu to spravne datum Martin tak tento příklad se mi hodně nelíbí. Takového programátora zatahat za uši ;-) Nebudu koukat do implementace Person, jak je napsaný hashCode a equals ... Určitě by každý normální programátor napsal toto: datumyNarozeni.get(p.getLogin()); V každém případě - původní dotaz je docela namístě. Úryvek ze stackoverflow mě úplně nepřesvědčil ... Kdyby člověk použil MapList, Something místo MapArrayList, Something, tak by to fungovalo i s ArrayList i s LinkedList. Fafi
Re: Proč není genericita v metodách Map jako get(), remove()?
2011/4/13 Ondřej Fafejta fafejta.ond...@gmail.com 2011/4/13 Martin Beránek martin.bera...@i.cz: Zdravím, našel jsem celkem rozumné vysvětlení: Restrikce se zavádějí proto, aby se něco nepokazilo. Mám-li to dohnat do umělého extrému (nebudu testovat výsledek na null), tak jestli odchytnu NPE nebo ClassCast je vcelku jedno :-) V každém případě - původní dotaz je docela namístě. Úryvek ze stackoverflow mě úplně nepřesvědčil ... Kdyby člověk použil MapList, Something místo MapArrayList, Something, tak by to fungovalo i s ArrayList i s LinkedList. Fafi Naprostý souhlas. Vkládat do mapy objekt s klíčem záměrně konkrétního typu a vytahovat to jiným mi přijde, přinejmenším, podivné. Ale co už, člověk se s tím naučí žít. -- Oto 'tapik' Buchta, ta...@buchtovi.cz, http://tapikuv.blogspot.com
Re: Proč není genericita v metodách Map jako get(), remove()?
2011/4/13 Miroslav Paulfranc paul...@seznam.cz Dobrý den. Myslím si, že datumyNarozeni.get(p.getLogin()); by nešlo použít, pokud by byl klíč složený z více položek. Pokud by objekt Person měl např. string name a string surname, nebo by došlo následně k dalšímu rozšíření - např. o rok narození, stačilo by myslím pouze náležitě změnit hash a equals a vše by pořád fungovalo. Pak ale nemohu přes michal vkládat do mapy. To bych musel použít třeba michal,ježek,1987-03-09 a odpovídajícím způsobem naimplementovat ten equals() a hashCode(). Ale co když někdo zapomene, že se teď už musí používat datum narození a zadá jenom michal,ježek? Původní zpráva Od: Ondřej Fafejta fafejta.ond...@gmail.com Předmět: Re: Proč není genericita v metodách Map jako get(), remove()? Datum: 13.4.2011 08:38:05 2011/4/13 Martin Beránek martin.bera...@i.cz: Zdravím, našel jsem celkem rozumné vysvětlení: Restrikce se zavádějí proto, aby se něco nepokazilo. Zavoláním get s jiným typem se nic nepokazí. Ještě trošku umělý příklad: MapString,Date datumyNarozeni = ... class Person { String fullName String login hashCode { return login.hashCode(); } equals(Object o) { return login.equals(o); } } datumyNarozeni.put(michal,new Date()); odnekud mi prijde objekt Person p kde je login michal, pak muzu udelat: datumyNarozeni.get(p) a dostanu to spravne datum Martin tak tento příklad se mi hodně nelíbí. Takového programátora zatahat za uši ;-) Nebudu koukat do implementace Person, jak je napsaný hashCode a equals ... Určitě by každý normální programátor napsal toto: datumyNarozeni.get(p.getLogin()); V každém případě - původní dotaz je docela namístě. Úryvek ze stackoverflow mě úplně nepřesvědčil ... Kdyby člověk použil MapList, Something místo MapArrayList, Something, tak by to fungovalo i s ArrayList i s LinkedList. Fafi -- Oto 'tapik' Buchta, ta...@buchtovi.cz, http://tapikuv.blogspot.com
Re: Proč není genericita v metodách Map jako get(), remove()?
Tak sem na to asi došel, viz příklad v příloze. Ono to totiž takovou mapu zadefinovat pomocí generik vlastně nejde... nebo jde, ale její použití pak bude silně limitující. Martin Dne 13.4.2011 07:44, Libor Jelinek napsal(a): Dobrý den! Studuju collection framework a mám k otázku rozhraní Map. To má uvedeno, že je to pár key-value K, V. /java.util Interface MapK,V Type Parameters:K - the type of keys maintained by this mapV - the type of mapped values/ Proč tedy metoda jako *containsKey()* je deklarována jako *containsKey(Object key)* a nikoli *containsKey(K key)*? Dále např. proč je *V get(Object key)* a nikoli *V get(K key)*? Poč je *V remove(Object key)* a nikoli *V remove(K key)*? -- Martin Beránek ICZ a.s., Pobočka Brno http://www.i.cz public class Main { static class BadMapK, V { void put(K key, V value) { } V get(K key) { return null; } } static class Foo {} static class ExtFoo extends Foo {} public static void main(String[] args) { BadMapFoo, String map1 = new BadMapFoo, String(); BadMapExtFoo, String map2 = new BadMapMain.ExtFoo, String(); readFromMap(map1); readFromMap(map2); // ERROR universalReadFromMap(map1); universalReadFromMap(map2); ; } public static void readFromMap(BadMapFoo, String m) { Foo f = new Foo(); m.get(f); } public static void universalReadFromMap(BadMap? extends Foo, String m) { Foo f = new Foo(); m.get(f); // ERROR } } smime.p7s Description: S/MIME Cryptographic Signature