在做关于购物删除时报错:
源码:
int id =Integer.parseInt(req.getParameter("id")) ;
List<OrderItem> orders = (ArrayList<OrderItem>)req.getSession().getAttribute("orders");
for(OrderItem order :orders) {
if(order.getProduct().getId()==id) {
orders.remove(order);
}
}
参考相关资料后得出结论:
报错原因:
1.实际上foreach语句内部实现是迭代器,不允许在此中删除后再次迭代,原因猜测是使用Iterator进行迭代的同时,移除了其中的对象,破坏了iterator内部用来迭代的索引,所以抛出异常
2.使用iterator(foreach内部实现)进行add、remove、clear、ensureCapacityInternal等,会改变modCound但没有改变expectedModCound 使两者不同则抛出异常
关于第二点的解释:
iterator。next方法
先来看实现Iterator遍历ArrayList, 抛出异常的是iterator.next()。看下Iterator next方法实现源码
其中:
modCount是ArrayList的一个属性,继承自抽象类AbstractList,用于表示ArrayList对象被修改次数。
protected transient int modCount = 0;
在创建Iterator的时候会将modCount赋值给expectedModCount, int expectedModCount = modCount; // 创建对象时初始化
复制代码 1 public E next() { 2 checkForComodification(); 3 int i = cursor; 4 if (i >= size) 5 throw new NoSuchElementException(); 6 Object[] elementData = ArrayList.this.elementData; 7 if (i >= elementData.length) 8 throw new ConcurrentModificationException(); 9 cursor = i + 1; 10 return (E) elementData[lastRet = i]; 11 } 12 13 final void checkForComodification() { 14 if (modCount != expectedModCount) 15 throw new ConcurrentModificationException(); 16 }
根据这两点原因得出解决方案:
1.for(OrderItem order :orders) {
if(order.getProduct().getId()==id) {
orders.remove(order);break;
}
} 在remove后加上break,即防止第一点原因出现,在进入iterator.next()之前结束循环。
2.使用for循环。
for (int i=0;i<orders.size();i++) {
if(orders.get(i).getProduct().getId()==id)
orders.remove(i);
}
参考文献: