views:

204

answers:

4

Why isn't a Map<String,List<SomeBean>> castable to Map<String,List<?>>?

What I'm doing now is this:

Map<String, List<SomeBean>> fromMap = new LinkedHashMap<String, List<SomeBean>>();

/* filling in data to fromMap here */

Map<String,List<?>> toMap = new LinkedHashMap<String, List<?>>();
for (String key : fromMap.keySet()) {
    toMap.put(key, fromMap.get(key));
}

In my opinion there should be a way around this manual transformation, but I can't figure out how. Any Ideas?

+1  A: 

If you really want to, you could cast to a raw Map (but what you want is not type safe):

Map<String,List<?>> toMap = (Map) new LinkedHashMap<String, List<String>>();
Fabian Steeg
I would suggest this if you are sure about the map types. It's ugly, but it works.
Ravi Wallau
+5  A: 

The cast is invalid because in Map<String,List<?>> you can put List<String> and List<WhatEver>, but not in Map<String, List<SomeBean>>.

For instance:

 //List<SomeBean> are ok in both lists
 fromMap.put("key", new ArrayList<SomeBean>());
 toMap.put("key", new ArrayList<SomeBean>());

 //List<String> are ok in Map<String,List<?>>, not in Map<String, List<SomeBean>>
 fromMap.put("key", new ArrayList<String>()); //DOES NOT COMPILE
 toMap.put("key", new ArrayList<String>());

To simplify your code, you may use the appropriate constructor to simplify your code:

 Map<String, List<SomeBean>> fromMap = new LinkedHashMap<String, List<SomeBean>>();
 Map<String,List<?>> toMap = new LinkedHashMap<String, List<?>>(fromMap);
Jerome
Aahh.. Now it does make sense! Thank you very much for you explanation!
cimnine
+3  A: 

Not realy an answer to your question, but as an extra: I would not use keyset here... If you want to iterate through all the elements of a map, use the entrySet() method. Its faster because it does not require the key-value lookup for each element.

for (Map.Entry<String, List<SomeBean>> entry : fromMap.entrySet()) {
  toMap.put(entry.getKey(), entry.getValue());
}
Fortega
nice to know, thank you!
cimnine
+1  A: 

When assigning to a Map, where K and V are not wildcard parameters, the Map being assigned must have exactly the same K and V. In your case, V must be exactly List<?>.

The workaround it to use a wildcard V.

Map<String, ? extends List<?>> map = new LinkedHashMap<String, List<String>>(); Because the V you are assigning to is a wildcard, the V being assigned must only be assignable to V (rather than being exactly V).

ILMTitan