In the application I’m developing, I make use of several maps associating strings to collections of elements, e.g. Map<String, List<String>>, Map<String, SortedSet<Object>>. In many cases I want simple functions to add/remove elements in the collection given by a certain key, possibly removing or creating new entries in the map.
I implemented some generic methods for the effect, but the putIntoCollection() method is giving me some problems. My implementation, which does not rise any warning, is the following:
public static <K, V, C extends Collection<V>> void putIntoCollection(
Map<K, C> map, K key, V value, Class<? extends C> collectionClass)
throws InstantiationException, IllegalAccessException {
C collection = map.get(key);
if (collection == null) {
collection = collectionClass.newInstance();
map.put(key, collection);
}
collection.add(value);
}
C represents the type of the collection, which can be any type of Collection, and the Class<? extends C> parameter allows me to pass a concrete class token to instantiate new C‘s (e.g. pass a token of ArrayList for a Map of Lists).
However, if I try to use it like this:
Map<String, Set<String>> tags;
String key, value;
MapUtilities.putIntoCollection(map, key, value, HashSet.class);
I get the compile error:
The parameterized method <K, V, Set<V>>putIntoCollection(Map<K,Set<V>>, K, V, Class<? extends Set<V>>) of type MapUtilities is not applicable for the arguments (Map<K,Set<V>>, K, V, Class<HashSet>)
I understand that happens because I’m passing a Class<HashSet> argument while it expects a parametrized Set class. However, I don’t know how (or if) can I obtain such instances of Class. Is there a better way to do a generic method such as this?
Are you in a position to use third-party libraries? You’re basically reinventing Guava’s
Multimap—ListMultimap<String, String>andSortedSetMultimap<String, Object>are your two examples. A bunch of implementations are provided — most notably, for your case,ArrayListMultimapandTreeMultimap.That said, it’s generally easier to just pass an explicit factory object: