Java使用for循环删除ArrayList符合条件元素仅删除部分是什么原因
问题原因
正向遍历ArrayList同时删除元素时会发生下标偏移问题:
- 调用
remove(i)删除下标为i的元素后,列表中i之后的所有元素都会向前移动一位,原本下标为i+1的元素会变为新的下标i - 下一次循环
i自增1,会直接跳过移动到i位置的元素,最终出现漏删
对应你的3个全符合删除条件的场景,执行逻辑如下:
- 初始列表元素下标为
0、1、2,第一次循环i=0,删除下标0的元素,剩余元素下标变为0(原下标1)、1(原下标2) i自增到1,判断当前下标1的元素(原下标2),删除后列表仅剩余1个元素(原下标1,当前下标0)i自增到2,此时列表size=1,i < package.size()条件不成立,循环结束,剩余的元素没有被校验删除
解决方案
以下是3种常用的正确实现方式:
1. 反向遍历删除
从列表尾部向前遍历,删除操作不会影响未遍历部分的下标:
// 注意:package是Java关键字,不能作为变量名,这里修改为packageList List<Package> packageList = new ArrayList<>(); packageList.addAll(package3); for (int i = packageList.size() - 1; i >= 0; i--) { if(packageList.get(i).getPlan().isEmpty()) { packageList.remove(i); } }
2. 使用迭代器Iterator删除
Java官方推荐的遍历删除集合元素的实现方式:
List<Package> packageList = new ArrayList<>(); packageList.addAll(package3); Iterator<Package> iterator = packageList.iterator(); while (iterator.hasNext()) { Package pkg = iterator.next(); if (pkg.getPlan().isEmpty()) { iterator.remove(); } }
3. Java 8+ 使用removeIf方法(最简洁)
直接调用JDK自带的过滤删除方法,一行代码完成需求:
List<Package> packageList = new ArrayList<>(); packageList.addAll(package3); packageList.removeIf(pkg -> pkg.getPlan().isEmpty());
内容的提问来源于stack exchange,提问作者Deividas.r
相关产品推荐
相关产品推荐

