我有一个List<ArrayList<Integer>>
的实例,如何将其更改为List<List<Integer>>
类型
我的解决方案是:
List<ArrayList<Integer>> list1 = new ArrayList<>();
list1.add(new ArrayList<>());
list1.add(new ArrayList<>());
List<List<Integer>> list2 = new ArrayList<>(list1);
但该方法耗时O(n)
,n
的长度相当于list1
。
问题1:有更好的方法吗?
下面的幼稚方法是编译错误:
List<List<Integer>> list2 = (List<List<Integer>>) list1;
问题2为什么上面的方法编译错误?
PS:这是一个实际问题。我只是将生产代码简化为上述问题。在产品代码中,它是List<SomeList>
,SomeList
实现List
接口,但具有List
中未声明的一些特殊函数。在中间过程中,我们要求内容必须是SomeList
,因为我们必须使用这些特殊的函数。然而,最后我们只需要将我们的结果输出到List<List>
供其他组使用。
首先,回答您的问题2:您的朴素强制转换不起作用的原因是因为它可能导致类型错误。例如,考虑下面的代码片段:
List<ArrayList<String>> list = new ArrayList<>();
List<List<String>> list2 = (List<List<String>>) list; // Wrong cast
list2.add(new LinkedList<>());
list.get(0).ensureCapacity(42); // Oops, LinkedList does not have this method.
关于你的问题1:在O(1)中做你想做的事情的类型安全方法是不存在的。您可以使用原始类型欺骗类型系统:
List<List<String>> list2 = (List) list;
但是这只会导致上面描述的问题,而不会导致编译器错误。但如果你确信这个列表之后永远不会改变,那么它可能是允许的。有时。但也许你真的不应该。
最好将第二个列表的类型更改为List<? extends List<String>>
。这将有效地禁止通过新的引用向list中添加元素,因为编译器无法根据list的类型来确定list2
中的list的类型:
List<ArrayList<String>> list = new ArrayList<>();
List<? extends List<String>> list2 = (List<? extends List<String>>) list;
list2.add(new LinkedList<>()); // Not possible anymore
list2.add(new ArrayList<>()); // Also not possible
从这个答案
List<List<Integer>> list2 = (List<List<Integer>>)(List<?>) list1;