ArrayList运行时出现IllegalStateException异常,求代码错误原因解析
搞定Java ArrayList迭代时的IllegalStateException异常
嘿,我来帮你拆解这个问题,先直接说结论:你触发异常是因为在调用Iterator.remove()之前,没有先调用Iterator.next(),违反了迭代器的使用规则。
代码里的问题出在哪?
先看你的代码片段:
import java.util.*; public class ArraylistExample2 { public static void main(String args[])throws Exception { ArrayList <String> al = new ArrayList<String>(); al.add("A");al.add("B");al.add("C"); Iterator <String> i = al.iterator(); while(i.hasNext()) { if(al.contains("B")) { i.remove(); // 这里就是问题所在! System.out.println(" Element B removed"); } System.out.println(i.next()); } } }
Java里的迭代器有严格的使用规则:
调用
remove()的前提是,必须刚调用过next()获取当前元素,而且在这之后还没调用过remove()(直到下一次next()之后才能再调用)。不满足这个条件就会抛出IllegalStateException。
你第一次进入循环时,直接检查al.contains("B")是true,然后立刻调用i.remove(),但此时你根本没调用i.next()去获取迭代器当前指向的元素,迭代器的状态不允许执行删除操作,所以直接触发了异常。
另外还有个小坑:用al.contains("B")来判断是否删除,会每次循环都遍历整个ArrayList,效率很低;而且如果列表里有多个"B",还会重复触发删除,进一步搞乱迭代器的状态。
修正后的正确写法
正确的姿势是先调用next()拿到当前元素,再判断是否要删除:
import java.util.*; public class ArraylistExample2 { public static void main(String args[])throws Exception { ArrayList <String> al = new ArrayList<String>(); al.add("A");al.add("B");al.add("C"); Iterator <String> i = al.iterator(); while(i.hasNext()) { String currentElement = i.next(); // 先拿元素,让迭代器走到正确的位置 if("B".equals(currentElement)) { i.remove(); // 现在调用remove就合法了,因为刚调用过next() System.out.println(" Element B removed"); } System.out.println(currentElement); } } }
这样改完之后,迭代器的状态始终是合规的,不会再抛出异常,同时也避免了contains()带来的性能浪费。
看堆栈信息怎么说
你的堆栈跟踪里明确标了java.lang.IllegalStateException来自java.util.ArrayList$Itr.remove(ArrayList.java:864),这就是ArrayList内部的迭代器实现里,检查到你没先调用next(),所以抛出了这个异常。
内容的提问来源于stack exchange,提问作者Sarvagya Dubey
相关产品推荐
相关产品推荐

