正确使用泛型与集合实例工厂

Proper use of generics with collection instance factory

我正在尝试使用 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");

但是我在调​​用 lazyMap 时收到以下编译器错误:

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>)

有什么正确的方法可以使用工厂在地图中生成列表吗?我也试过这个:

Map<Integer, List<String>> namesPerNumber = 
            MapUtils.lazyMap(
                new HashMap<Integer, List<String>>(), 
                FactoryUtils.<List<String>instantiateFactory(ArrayList.class));

但是我在调​​用 instantiateFactory 时遇到了这个错误:

The parameterized method <List<String>>instantiateFactory(Class<List<String>>) of type FactoryUtils is not applicable for the arguments (Class<ArrayList>)

我找到的唯一可行的解​​决方案如下,但我觉得它很丑陋:

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>();
                    }
                });

感谢任何帮助。

已签名,
失能药

由于类型擦除,class 文字仅支持具体化类型或原始类型,因此 ArrayList.class 表示原始类型 ArrayList,而不是预期的 ArrayList<String>

解决这个问题的一种方法是使用一个未经检查的操作:

@SuppressWarnings("unchecked") Class<ArrayList<String>> type = (Class)ArrayList.class;

Map<Integer, List<String>> namesPerNumber = 
    MapUtils.lazyMap(
        new HashMap<Integer, List<String>>(), 
        FactoryUtils.instantiateFactory(type));

请注意,@SuppressWarnings("unchecked") 的效果有意限于此处的单个未检查操作。

或者你使用

Map<Integer, List<String>> namesPerNumber = 
    MapUtils.lazyMap(
        new HashMap<Integer, List<String>>(), 
        FactoryUtils.prototypeFactory(new ArrayList<String>()));

相反。

如果您使用的是 Java 8,最佳选择是

Map<Integer, List<String>> namesPerNumber = 
    MapUtils.lazyMap(new HashMap<>(), () -> new ArrayList<>());