java循环结构之for循环打印做俯卧撑_增强for循环 java.util.ConcurrentModificationException...

Java中的Iterator功能比较简单,并且只能单向移动:

(1) 使用方法iterator()要求容器返回一个Iterator。第一次调用Iterator的next()方法时,它返回序列的第一个元素。注意:iterator()方法是java.lang.Iterable接口,被Collection继承。

(2) 使用next()获得序列中的下一个元素。

(3) 使用hasNext()检查序列中是否还有元素。

(4) 使用remove()将迭代器新返回的元素删除。

迭代器应用:

list l = new ArrayList();

l.add("aa");

l.add("bb");

l.add("cc");

for (Iterator iter = l.iterator(); iter.hasNext();) {

String str = (String)iter.next();

System.out.println(str);

}

/*迭代器用于while循环

Iterator iter = l.iterator();

while(iter.hasNext()){

String str = (String) iter.next();

System.out.println(str);

}

*/

Iterator升级

在AbstractList中还有一个内部类Itr,Itr implements Iterator,Itr是一个List遍历的工具类,当然list.iterator()方法也是返回Itr对象,在Itr中有一个校验位属性expectedModCount,对于一个Itr对象,其初始时expectedModCount=modCount。

【注】在AbstractList中,有一个属性modCount,这个属性是跟踪List中数据被修改的次数,任何对List的add/remove操作,都将导致modCount++。

Iterator是List一个视图,其最终还是操作List的存储结构。在使用iterator遍历时,remove()操作,会导致modCount++,因为有expectedModCount=modCount,即在 iterator中remove数据,会带来expectedModCount与modCount值的同步。

在Iterator遍历时,next(),remove()方法会校验expectedModCount与modCount值是否一致,如果不一致,就意味着这List数据在iterator外部被修改,此时iterator遍历将会造成 ConcurrentModificationException。

AbstractList不仅支持普通的Iterator,还支持ListIterator(ArrayList,LinkedList均支持),ListIterator增加了遍历时双向游标能力(previous,next),增加了add方法。add方法和remove方法一样也做了expectedModCount和modCount一致性校验。

在单线程操作的情况下,在DAO层查询到数据集合后,返回到service层做业务处理,要求:遍历数据集合,判断不符合条件的元素,做删除操作。

在用foreach和 Iterator 都会发生java.util.ConcurrentModificationException。

看一下JavaDoc对java.util.ConcurrentModificationException异常的描述:

当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。

查看源码后终于发现了原因是因为:

迭代器的modCount和expectedModCount的值不一致。

单线程中该异常出现的原因是:对一个集合遍历的同时,有对该集合进行了增删的操作。导致AbstarctList的modCount和expectedModCount的值不一致。

而我们要做的就是将需要操作的元素放到中间元素中,并记录操作标志位。在遍历结束后进行增删操作。

或自定义迭代器复写其中的相关操作,在操作结束后添加expectedModCount = modCount;

多线程中更容易出现该异常,当你在一个线程中对一数据集合进行遍历,正赶上另外一个线程对该数据集合进行增删操作。

解决方案:

1)在使用iterator迭代的时候使用synchronized或者Lock进行同步;

2)使用并发容器CopyOnWriteArrayList代替ArrayList和Vector。

以下是Demo:推荐大家使用for循环进行遍历集合,在for循环中做增删操作。

importjava.util.ArrayList;importjava.util.Iterator;importjava.util.List;public classTest {//出现java.util.ConcurrentModificationException

public List m1(Listlist) {for(String temp : list) {if ("3".equals(temp)) {

list.remove(temp);

}

}returnlist;

}//出现java.util.ConcurrentModificationException

public List m2(Listlist) {

Iterator iterator =list.iterator();while(iterator.hasNext()) {

String temp=iterator.next();if ("3".equals(temp)) {

list.remove(temp);

}

}returnlist;

}//successful!

public List m3(Listlist) {for (int i = 0; i < list.size(); i++) {if ("3".equals(list.get(i))) {

list.remove(i);

}

}returnlist;

}public static voidmain(String[] args) {

List list = new ArrayList();

list.add("1");

list.add("2");

list.add("3");

Test test= newTest();

List listTemp =test.m1(list);

System.out.println(listTemp.toString());

}

}

Iterator 在工作的时候是不允许被迭代的对象被改变的。

但你可以使用 Iterator 本身的方法 remove() 来删除对象,Iterator.remove() 方法会在删除当前迭代对象的同时维护索引的一致性。

正确的在遍历的同时删除元素的姿势:

Iterator stuIter =students.iterator();while(stuIter.hasNext()) {

Student student=stuIter.next();if (student.getId() == 2)

stuIter.remove();//这里要使用Iterator的remove方法移除当前对象,如果使用List的remove方法,则同样会出现ConcurrentModificationException

}

参考:https://mp.weixin.qq.com/s?__biz=MzI3NzE0NjcwMg%3D%3D&mid=2650121134&idx=1&sn=a34a1bd547f00e479e9f6dbde8848fe4&chksm=f36bbe8fc41c3799d1bb2c781f81f51e28651d2fb8eb5670a31caac5ba782b66416e5fdf1b1c&mpshare=1&scene=23&srcid=0414ouzb2yYypPWh2K0QVhtY%23rd

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值