遍历嵌套列表时,调用子列表clear方法为何会缩短父列表长度?
问题解答
问题1:为何调用子列表的clear()会影响父列表的遍历?
ListUtils.partition(Apache Commons Collections工具类)返回的不是独立的子列表集合,而是原列表的动态分区视图——每个子分区本质是原列表的subList实例,和原列表共享底层数据。
当你对这类子列表调用clear()时,实际效果是直接从原列表中删除对应范围的元素。而分区列表本身是动态计算的,每次访问都会基于原列表的实时状态重新生成分区,这就导致遍历过程中,原列表的变化会打乱迭代器的遍历逻辑,看起来像是子列表被“移除”了。
问题2:代码中调用clear()后为何numberBatches的遍历长度缩短?
结合你的代码和输出,具体过程如下:
- 初始状态:原列表
numbers有10个元素,partition(numbers, 2)生成5个分区:[1,2],[3,4],[5,6],[7,8],[9,10] - 第一次循环:遍历第一个分区
[1,2],打印后调用clear()——这会删除原列表前2个元素,numbers变为[3,4,5,6,7,8,9,10] - 动态分区更新:此时
numberBatches的分区会基于原列表的新状态重新计算,变为4个分区:[3,4],[5,6],[7,8],[9,10] - 迭代器偏移:增强for循环的迭代器是动态的,第一次迭代完成后,游标指向原分区列表的第2个位置,但此时原列表的元素索引已前移,该位置对应的新分区是
[5,6],直接跳过了[3,4] - 重复上述逻辑:每次调用
clear()都会缩短原列表,迭代器的游标会持续跳过原本的下一个分区,最终只遍历了[1,2]、[5,6]、[9,10]三个分区,对应输出的结果。
解决方案
如果需要独立的分区,不受原列表变化影响,将每个分区拷贝为独立的列表即可:
ArrayList<String> numbers = new ArrayList<>(Arrays.asList("1", "2", "3", "4", "5", "6", "7", "8", "9", "10")); // 拷贝每个分区为独立列表 List<List<String>> numberBatches = new ArrayList<>(); for (List<String> batch : ListUtils.partition(numbers, 2)) { numberBatches.add(new ArrayList<>(batch)); } // 此时调用clear()只会清空当前子列表,不会影响原列表和其他分区 for(List<String> numberBatch : numberBatches) { for(String number : numberBatch) { System.out.println(number); } numberBatch.clear(); }
内容的提问来源于stack exchange,提问作者Half_Duplex
相关产品推荐
相关产品推荐

