Reputation: 2683
I'm trying to do the following thing using Apache Commons Collections v4:
Map<Integer, List<String>> namesPerNumber =
MapUtils.lazyMap(
new HashMap<Integer, List<String>>(),
FactoryUtils.instantiateFactory(ArrayList.class));
namesPerNumber.get(1).add("Mickey");
But I get the following compiler error at the lazyMap call:
The method lazyMap(Map<K,V>, Factory<? extends V>) in the type MapUtils is not applicable for the arguments (HashMap<Integer,List<String&t;>, Factory<ArrayList>)
Is there any proper way to use the factory for generating lists in a map? I tried also this:
Map<Integer, List<String>> namesPerNumber =
MapUtils.lazyMap(
new HashMap<Integer, List<String>>(),
FactoryUtils.<List<String>instantiateFactory(ArrayList.class));
But then I get this error at the instantiateFactory call:
The parameterized method <List<String>>instantiateFactory(Class<List<String>>) of type FactoryUtils is not applicable for the arguments (Class<ArrayList>)
The only working solution I found is the following, but I find it ugly:
Map<Integer, List<String>> namesPerNumber3 =
MapUtils.lazyMap(
new HashMap<Integer, List<String>>(),
new Factory<List<String>>() {
@Override
public List<String> create() {
return new ArrayList<String>();
}
});
Any help appreciated.
Signed,
lostingenerics
Upvotes: 1
Views: 365
Reputation: 298143
Due to type erasure, class literals support only reifiable types or raw types, so ArrayList.class
represents the raw type ArrayList
, not the intended ArrayList<String>
.
One way to solve this, is by using one unchecked operation:
@SuppressWarnings("unchecked") Class<ArrayList<String>> type = (Class)ArrayList.class;
Map<Integer, List<String>> namesPerNumber =
MapUtils.lazyMap(
new HashMap<Integer, List<String>>(),
FactoryUtils.instantiateFactory(type));
Note that the effect of @SuppressWarnings("unchecked")
is intentionally limited to the single unchecked operation here.
Or you use
Map<Integer, List<String>> namesPerNumber =
MapUtils.lazyMap(
new HashMap<Integer, List<String>>(),
FactoryUtils.prototypeFactory(new ArrayList<String>()));
instead.
If you are using Java 8, the best option is
Map<Integer, List<String>> namesPerNumber =
MapUtils.lazyMap(new HashMap<>(), () -> new ArrayList<>());
Upvotes: 3