11

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?

6 Answers 6

20

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:

Sign up to request clarification or add additional context in comments.

1 Comment

You can also use Map<Integer, ? extends Map<String, Integer>> myMap = new HashMap<Integer, HashMap<String, Integer>>();
10

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>(); 

Comments

6

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

Comments

3

you need something like this:

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

Comments

3

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

Comments

2

Try this:

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.