The 4.0 release of the Apache Commons Collections library has added generics support. I am having trouble converting my code to take advantage of it:
I would like a MultiValueMap
which takes a String as a key, and a collection of Strings as the value. But:
LinkedHashMap
)LinkedHashSet
).The closest I can get is:
MultiValueMap<String, String> orderedMap = MultiValueMap.multiValueMap(
new LinkedHashMap<String, Collection<String>>(),
LinkedHashSet.class
);
But that produces the error:
The method
multiValueMap(Map<K,? super C>, Class<C>)
in the typeMultiValueMap
is not applicable for the arguments(LinkedHashMap<String,Collection<String>>, Class<LinkedHashSet>)
So now I am in generics hell. Any suggestions would be most welcome.
Prior to version 4.0, I accomplished that with the following:
MultiValueMap orderedMap = MultiValueMap.decorate(
new LinkedHashMap<>(),
LinkedHashSet.class
);
Simple! I provide the LinkedHashMap
to decorate with MultiValueMap
behaviour, and specify the type of collection (LinkedHashSet
) to use as the values. But that requires casting when I call put()
and get()
and so I'd like to be able to use the new generic version provided by 4.0.
A MultiValueMap decorates another map, allowing it to have more than one value for a key. A MultiMap is a Map with slightly different semantics. Putting a value into the map will add the value to a Collection at that key. Getting a value will return a Collection, holding all the values put to that key.
A map cannot contain duplicate keys; each key can map to at most one value. So in a MultivaluedMap you can insert 0, 1, 2, 3 or more objects related to the same key. In a Map you can insert exactly 1 object related to a key.
Commons Collections was introduced as a series of utilities that augment the Java Collections API. Commons Collections contains functors such as Predicate and Closure , utilities for filtering and selecting elements in a collection, and some new collections: Bag and Buffer .
The Apache Commons Collections are the components of the Apache Commons which are derived from Java API and provides component architecture for the Java language. Commons-Collections seek to build upon the JDK classes by providing new interfaces, implementations and utilities.
I consulted the Apache Commons Collections mailing list, where it was explained to me that the interface for MultiValueMap
is known to be lacking, but will be revamped in version 4.1 (see here for the JIRA issue and associated discussion).
So in the future we may have a better solution, but in the meantime, as Rohit Jain mentioned in his answer, we're just going to have to suppress some warnings. However, since the key aspect of type safety is for the MultiValueMap
(not the custom collection type), the simplest way to achieve this is:
@SuppressWarnings({ "rawtypes", "unchecked" })
MultiValueMap<String, String> orderedMap =
MapUtils.multiValueMap(new LinkedHashMap(), LinkedHashSet.class);
Note the use of the MapUtils
factory method, rather than the more direct MultiValueMap
which I had used in my original question.
The problem is you need to pass a Class<LinkedHashSet<String>>
as second argument. That you can't create directly. You need to do some cast.
This will work fine:
@SuppressWarnings("unchecked")
MultiValueMap<String, String> orderedMap =
MultiValueMap.multiValueMap(
new LinkedHashMap<String, Collection<String>>(),
(Class<LinkedHashSet<String>>)(Class<?>)LinkedHashSet.class
);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With