为何第二个for循环无法完整打印ArrayList?
问题分析与解决方案:ArrayList遍历删除时的元素遗漏问题
你遇到的情况很典型——第一个for循环能完整打印所有元素,但第二个循环里的'2'就是没出现在控制台,而且你本来想实现保留第一个元素(无论是否为字符)+ 其余非字符元素的目标,结果却出了问题。
核心问题原因
问题出在遍历ArrayList时同时执行remove操作,导致索引混乱,咱们一步步拆解你的代码逻辑:
- 初始ArrayList有两个元素:
'a'(索引0)、'2'(索引1) - 第二个循环启动,i=0:
- 打印
'a',判断它是字母(ASCII在65-122区间),执行al.remove(0) - 此时ArrayList只剩
'2',它的索引自动变成了0
- 打印
- 循环继续,i自增到1,而此时
al.size()已经变成1,i < al.size()(1 < 1)不成立,循环直接结束- 所以
'2'根本没机会进入循环被打印,自然就看不到输出了
- 所以
两种可行解决方案
方案一:倒序遍历(最直接的修复方式)
倒着遍历的话,删除前面的元素不会影响后面未遍历元素的索引,完美避开索引混乱问题。同时我们可以直接从索引1开始遍历,确保第一个元素不被处理:
import java.util.ArrayList; public class Test1 { public static void main(String[] args) { ArrayList<Character> al = new ArrayList<>(); al.add('a'); al.add('2'); // 第一个循环正常打印所有元素 for(int i=0;i<al.size();i++){ System.out.println("element entered in for loop: "+al.get(i)); } // 倒序遍历,从索引1开始(保留第一个元素) for(int i = al.size() - 1; i >= 1; i--){ System.out.println("element entered for check: "+al.get(i)); char c = al.get(i); // 直接用字符常量判断范围,比ASCII数字更直观 if((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')){ al.remove(i); } } // 打印处理后的结果验证 System.out.println("处理后的ArrayList元素:"); for(Character obj : al){ System.out.println(obj); } } }
方案二:使用Iterator(Java官方推荐的遍历删除方式)
Java中遍历集合并删除元素,最安全的方式是用Iterator,它会自动同步集合状态,完全避免索引问题:
import java.util.ArrayList; import java.util.Iterator; public class Test1 { public static void main(String[] args) { ArrayList<Character> al = new ArrayList<>(); al.add('a'); al.add('2'); // 第一个循环正常打印所有元素 for(int i=0;i<al.size();i++){ System.out.println("element entered in for loop: "+al.get(i)); } // 使用Iterator处理,保留第一个元素 Iterator<Character> iterator = al.iterator(); // 先取出第一个元素,直接保留 if(iterator.hasNext()){ System.out.println("保留第一个元素:"+iterator.next()); } // 遍历剩余元素 while(iterator.hasNext()){ char c = iterator.next(); System.out.println("element entered for check: "+c); if((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')){ iterator.remove(); // 用Iterator的remove方法,不会有索引混乱 } } // 打印处理后的结果验证 System.out.println("处理后的ArrayList元素:"); for(Character obj : al){ System.out.println(obj); } } }
额外优化建议
- 把代码里的
&换成&&:&&是短路与,效率更高,逻辑也更符合常规需求 - 给ArrayList指定泛型(比如
ArrayList<Character>):避免强制类型转换,代码更安全可读 - 判断字符范围时用
'A'、'z'这类字符常量:比直接写ASCII数字65、122可读性强很多
内容的提问来源于stack exchange,提问作者Sainath Pawar
相关产品推荐
相关产品推荐

