遍历ArrayList时添加元素遇问题:外层循环仅执行一次求助
问题分析与解决方案
我一眼就看出问题出在ListIterator的cursor位置管理上!你的代码逻辑看起来没问题,但ListIterator的add()方法的行为和你预想的不一样,直接导致了外层循环只执行一次。
问题根源拆解
我们一步步走一遍你的代码执行流程:
- 初始时
dirs只有一个根目录,ListIterator的cursor(迭代器的当前位置)停在索引0处。 - 第一次外层循环:
iterator.hasNext()返回true,调用iterator.next()取出根目录,此时cursor会移动到索引1的位置(根目录的下一位)。 - 遍历根目录的子文件时,每调用一次
iterator.add(file),新目录会被插入到当前cursor的位置,然后cursor自动移动到新元素的后面。比如你添加了3个子目录,最后cursor会停在索引1+3=4的位置,而此时dirs的总大小是1+3=4。 - 外层循环准备下一次迭代时,
iterator.hasNext()会检查cursor是否小于列表大小——此时cursor等于列表大小,返回false,循环直接终止,新添加的子目录根本没机会被遍历到!
修正方案:用索引遍历替代ListIterator
想要遍历动态增长的列表,用普通的索引遍历是最直观且不易出错的方式。我们可以用while循环配合索引来实现:
int i = 0; while (i < dirs.size()) { File currentDir = dirs.get(i); i++; // 先递增索引,避免后续添加元素影响当前迭代 // 避免listFiles()返回null导致空指针 File[] files = currentDir.listFiles(); if (files == null) { continue; } for (File file : files) { if (checkCondition(file)) { fileList.add(file); } if (file.isDirectory()) { dirs.add(file); // 直接添加到列表末尾 } } }
为什么这个方案能工作?
- 我们用索引
i来跟踪当前要处理的目录,每次处理完一个目录后先递增i,这样即使后续向dirs添加新元素,也不会打乱当前的迭代顺序。 - 循环条件
i < dirs.size()会动态判断:每次添加新目录后,dirs.size()会变大,i会一直走到列表的最新长度,确保所有目录(包括动态添加的)都会被处理。
额外提示
别忘了处理currentDir.listFiles()返回null的情况——当目录没有读取权限、不是目录或者不存在时,这个方法会返回null,直接遍历会抛出NullPointerException,所以加个判断很有必要。
内容的提问来源于stack exchange,提问作者Yes92
相关产品推荐
相关产品推荐

