Java中能否在O(1)时间将List<ArrayList<Integer>>转为List<List<Integer>>
问题1:是否存在更优的实现方法?
存在O(1)时间复杂度的实现方案,可根据场景选择:
- 如果可以和下游使用方约定返回列表的使用规则,你可以直接通过双重类型强转实现:
List<List<Integer>> list2 = (List<List<Integer>>) (List<?>) list1;
这种方案没有额外的拷贝开销,但是必须保证后续不会有人往list2中插入非ArrayList(你的生产场景下对应非SomeList)的其他List实现类实例,否则运行时会抛出类型转换异常。
- 如果需要保证类型安全,避免下游误用,你可以用不可变视图包装:
List<List<Integer>> list2 = Collections.unmodifiableList(list1);
这种方案同样是O(1)时间复杂度,返回的列表禁止add/remove等修改操作,既避免了元素拷贝开销,也杜绝了下游插入非法类型的风险。
如果下游确实需要修改返回的列表结构,那你原来的O(n)浅拷贝方案已经是最优的,因为仅拷贝元素引用的开销极低,绝大多数场景下不会成为性能瓶颈。对应你的生产场景,因为对外输出只需要提供List类型供其他团队使用,不需要修改列表结构的话,用不可变视图包装的方案是最稳妥的。
问题2:直接强转为什么编译报错?
这是Java泛型的不变性规则导致的:虽然ArrayList实现了List接口,但List<ArrayList<Integer>>和List<List<Integer>>之间不存在继承关系,编译器直接禁止这种强转,本质是为了避免类型安全漏洞。
假设允许这种强转,后续代码就可以往List<List<Integer>>类型的变量里插入LinkedList<Integer>实例,那么原List<ArrayList<Integer>>类型的列表里就会出现不符合类型声明的元素,运行时会出现隐性的类型错误。
内容的提问来源于stack exchange,提问作者maplemaple
相关产品推荐
相关产品推荐

