0

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?

5
  • it works on my JDK 6 Eclipse.. Commented Dec 21, 2009 at 12:44
  • I would be very surprised if the cast worked in your Eclipse. Are you talking about the given snippet? Commented Dec 21, 2009 at 12:52
  • yeah, I meant the snippet works.. Commented Dec 21, 2009 at 12:59
  • @Bozho: Shure, because that was my work-around. But this was what I tried, and that doesn't compile: Map<String,List<?>> toMap = (Map<String,List<?>>) new Map<String, List<SomeBean>>(). ~Chris Commented Dec 21, 2009 at 13:04
  • Gilad Bracha's [Generics in the Java Programming Language] (java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf) paper is an excellent source of information on generics. Commented Dec 21, 2009 at 16:55

4 Answers 4

5

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);
Sign up to request clarification or add additional context in comments.

1 Comment

Aahh.. Now it does make sense! Thank you very much for you explanation!
3

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

Comments

1

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

1 Comment

I would suggest this if you are sure about the map types. It's ugly, but it works.
1

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).

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.