是否可以<Integer><Integer>在 Java 中以 O(1) 时间将 List<ArrayList> 的实例转换为 List<List>?



我有一个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;

最新更新