我们在敲代码的过程中,难免会和一些Exception不期而遇,就像不知什么时候就会触碰到的女朋友的小脾气,并且,Exception也正像女朋友一样,你需要花上一些时间去了解对方,才知道自己是怎么“死”的。和ConcurrentModificationException的初相遇,那是在一个秋末夜晚,昏黄的路灯下……好了,不扯了。
现在,我们来会一会而ConcurrentModificationException。问题出现在做一个模拟影院自主购票的控制台小项目的过程中,需要一个方法来将选中的电影加入到购物车列表。具体如下。
Iterator<MovieInCart> it = chosenList.iterator();
if(it.hasNext()==false){ //购物车列表为空
chosenList.add(movieInCart);<span style="white-space:pre"> </span> //直接将该电影加入购物车列表
}else{
while(it.hasNext()){ //判断购物车列表里是否已经有该电影
<strong>MovieInCart movieExisted = it.next();//该语句报错 ConcurrentModificationException</strong>
if(movieInCart.equals(movieExisted)){//有的话 仅更改已存在的该电影的购买数量
movieExisted.setQuantity(movieExisted.getQuantity()+quantity);
} else{
chosenList.add(movieInCart);//没有的话 将该电影加入购物车列表
}
}
}
解决
while(it.hasNext()){ //判断购物车列表里是否已经有该电影
MovieInCart movieExisted = it.next();
if(movieInCart.equals(movieExisted)){//有的话 仅更改已存在的该电影的购买数量
movieExisted.setQuantity(movieExisted.getQuantity()+quantity);
} else{
chosenList.add(movieInCart);//没有的话 将该电影加入购物车列表
<strong>break;//程序若能执行到此,已将选择的电影添加,无需在进行下一次循环</strong>
}
}另外用增强的for循环的话,也一样加break;即解决问题,只是代码与用迭代器稍有不同,本文在后面也会讲到。 for(MovieInCart movieExisted:chosenList){
if(movieInCart.equals(movieExisted)){//有的话 仅更改已存在的该电影的购买数量
movieExisted.setQuantity(movieExisted.getQuantity()+quantity); break; //有一个满足条件修改后的即退出循环</strong> } else{
chosenList.add(movieInCart);//没有的话 将该电影加入购物车列表 break; //添加后即退出循环 }
}进一步
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}int lastRet = -1; // index of last element returned; -1 if no such 最后一个元素的下标,没有元素则为-1
int expectedModCount; //初始为modCount,作用是使迭代器的修改次数与ArrayList的相同。
public void add(E e) {
checkForComodification();
try {
int i = cursor;
ArrayList.this.add(i, e);
<strong>cursor = i + 1;</strong>
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
查看add(E e)方法的代码我们可以知道,那会对迭代器的游标cusor进行+1操作,而同时add(E e)方法本质还是调用了add(int index, E e)两个参数的方法: public void add(int index, E e) {
rangeCheckForAdd(index);
checkForComodification();
parent.add(parentOffset + index, e);
this.modCount = parent.modCount;
this.size++;
}
还有什么
for(MovieInCart movieExisted:chosenList){
<span style="white-space:pre"> </span>if(movieInCart.equals(movieExisted)){//有的话 仅更改已存在的该电影的购买数量
movieExisted.setQuantity(movieExisted.getQuantity()+quantity);
} else{
chosenList.add(movieInCart);//没有的话 将该电影加入购物车列表
}
}然而,运行程序再次调试,却出现了和用迭代器一模一样的出此同一位置的异常:说明,增强的for循环的本质,还是迭代器,只不过是隐含的。所以我们还是要在add()方法后加上break; 。
for(MovieInCart movieExisted:chosenList){
if(movieInCart.equals(movieExisted)){//有的话 仅更改已存在的该电影的购买数量
movieExisted.setQuantity(movieExisted.getQuantity()+quantity); break; //有一个满足条件修改后的即退出循环</strong>
} else{
chosenList.add(movieInCart);//没有的话 将该电影加入购物车列表 break; //添加后即退出循环
}
}
2552



被折叠的 条评论
为什么被折叠?



