Recently, I've been using a lot of Guava Multimap.
Occasionally, I need to convert between a Multimap<K,V>
and Map<K, Collection<V>
. One direction is already provided by the Guava API: Multimap#asMap()
. For the other direction, I wrote a simple utility method as follows:
public static <K,V> Multimap<K,V> multimapFromMap(Map<K, Collection<V>> map) {
Multimap<K,V> mmap = HashMultimap.create();
for (Map.Entry<K,Collection<V>> entry : map.entrySet())
mmap.putAll(entry.getKey(), entry.getValue());
return mmap;
}
But when I tried writing
Map<String, Set<String>> aMap = ... ; // obtained from elsewhere
Multimap<String, String> mMap = multimapFromMap(aMap);
I get this error message:
multimapFromMap(java.util.Map<String, java.util.Collection<?>>) cannot be applied to (java.util.Map<java.lang.String, java.util.Set<java.lang.String>>)
But since the Set
interface extends the Collection
interface, shouldn't my code be okay?
From Oracle Java Generics tutorial page, I see the example " ... ArrayList<E>
implements List<E>
, and List<E>
extends Collection<E>
. So ArrayList<String>
is a subtype of List<String>
, which is a subtype of Collection<String>
. So long as you do not vary the type argument, the subtyping relationship is preserved between the types."
Additions based on comments
- I replaced
V
withString
in themultimapFromMap
method, just to reassure myself that I wasn't getting some generics-related concepts confused, but the error persists with?
replaced withjava.lang.Object
in the error message.