Tushar Trivedi
Tushar Trivedi

Reputation: 400

Collection object creation using Generics

When I try to create object as below :

Map<Integer, Map<String, Integer>> myMap = new HashMap<Integer, HashMap<String, Integer>>();

What is wrong syntactically, can any one explain me?

Upvotes: 11

Views: 515

Answers (6)

AmitG
AmitG

Reputation: 10553

It is similar error like

List<Animal> list = new ArrayList<Dog>();

Parameterized type should be of same type at both end. There is no inheritance (IS-A) concept. If you still want to use it then use wildcard(?) with extend/super keyword which is allowed only at left side of the equals sign.

List<Animal> list = new ArrayList<Dog>(); // is not allowed

but

Animal[] animal = new Dog[10];  //is allowed
animal[0] = new Dog(); // is allowed

where it will later fail and throw exception if somebody tries to add Cat (extends Animal) object.

animal[1] = new Cat();  //compiles fine but throws java.lang.ArrayStoreException at Runtime.

Remember animal[1] or animal[index] is holding reference of Dog. So Dog reference variable can refer to Dog object not Cat object.

So to avoid such scenario, JSL have made such changes in generics list/Collection. This answer is also applicable for your question(Map).
Parameterized type should be of same type at both end.

List<Animal> list = new ArrayList<Animal>(); 

Upvotes: 10

Evgeniy Dorofeev
Evgeniy Dorofeev

Reputation: 136162

Try this

Map<Integer, ? extends Map<String, Integer>> myMap = new HashMap<Integer, HashMap<String, Integer>>();

It is easer to explain on a simpler example

Set<Number> set = new HashSet<Integer>();

is not allowed, because then you could add a Double to HashSet of Integers

set.add(1.0)

Note that

Set<? extends Number> set = new HashSet<Integer>();

does not allow to add anything but null to the set. But you can only read Numbers from it

You can find more info here http://docs.oracle.com/javase/tutorial/extra/generics/wildcards.html

Upvotes: 6

Reimeus
Reimeus

Reputation: 159874

Generics are not co-variant. You can use:

Map<Integer, Map<String, Integer>> myMap = new HashMap<Integer, Map<String, Integer>>();
^                                                                ^
--------------^------------------- becomes ------^               |
              -----------------must remain as type ---------------

While the Map on the outer left hand side of the assignment can "become" a HashMap as assigned, the same cannot be applied to any types that appear as generic parameters.

Edit:

As noted by @Keppil, you can use the bounded wildcard syntax:

Map<Integer, ? extends Map<String, Integer>> myMap = new HashMap<Integer, HashMap<String, Integer>>();

Note that this syntax will not allow entries to be added to the map but is useful as a type to be passed to and from methods.

Some references:

Upvotes: 20

Mohan Raj B
Mohan Raj B

Reputation: 1026

Map<String, Integer> is not same as HashMap<String, Integer>. Thats the problem.

Actually HashMap implements Map interface. So it should be ? extends Map<String, Integer> on left hand side

Upvotes: 3

Stephan
Stephan

Reputation: 8090

you need something like this:

Map<Integer, Map<String, Integer>> myMap = new HashMap<Integer, Map<String, Integer>>();
myMap.put(1, new HashMap<String, Integer>());

Upvotes: 3

Achintya Jha
Achintya Jha

Reputation: 12843

Try this:

Map<Integer, HashMap<String, Integer>> myMap = new HashMap<Integer, HashMap<String, Integer>>();

Upvotes: 2

Related Questions