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
VwithStringin themultimapFromMapmethod, just to reassure myself that I wasn't getting some generics-related concepts confused, but the error persists with?replaced withjava.lang.Objectin the error message.