Re: Proč není genericita v metodách Map jako get(), remove()?

2011-04-13 Tema obsahu Josef Cacek
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()?

2011-04-13 Tema obsahu Martin Beránek

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-04-13 Tema obsahu Ondřej Fafejta
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-04-13 Tema obsahu Miroslav Paulfranc
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-04-13 Tema obsahu Oto Buchta
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-04-13 Tema obsahu Oto Buchta
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()?

2011-04-13 Tema obsahu Martin Beránek
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