java基础——java.util.ConcurrentModificationException

在编写代码的时候,有时候会遇到List里有符合条件的的对象,就移除改对象!
但是这种操作如:使用了 List 的remove,会导致一些很严重的问题!
如下这段代码使用ArrayList:

@Test
    public void testRemoveList(){
        List<String> list = new ArrayList<String>();
        list.add("A");
        list.add("B");
        list.add("C");
        list.add("D");
        list.add("E");
        for (String string : list) {
            System.out.println(string);
            if("C".equals(string)){
                list.remove(string);
            }
        }
    }

程序运行,报错!!!

java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
    at java.util.ArrayList$Itr.next(ArrayList.java:831)
    at com.test.common.TestCommon.testRemoveList(TestCommon.java:318)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

这里写图片描述

千万要记住,不要在循环集合的时候去操作集合的长度!!!!
千万要记住,不要在循环集合的时候去操作集合的长度!!!!
千万要记住,不要在循环集合的时候去操作集合的长度!!!!

这里在小小的说一下,foreach 这个循环,它的原理底层实现其实是
使用了 Iterator!

解决方法,
(1)使用一个临时的集合,如下代码:

@Test
    public void testRemoveList(){
        try {//如果是不重要的业务代码。可以加上try-catch 不要影响主流程的进行

            List<String> list = new ArrayList<String>();
            list.add("A");
            list.add("B");
            list.add("C");
            list.add("D");
            list.add("E");

            if(list.size() > 0){//循环List一定去判断 非null  和  List-size() > 0
                List<String> templist = new ArrayList<String>();
                for (String string : list) {
                    System.out.println(string);
                    if(!"C".equals(string)){
                        templist.add(string);
                    }
                }
                System.out.println(templist.toString());
            }


        } catch (Exception e) {
            e.printStackTrace();
        }

    }

总结,其实这个是一个fail-fast 机制

fail-fast 机制是java集合(Collection)中的一种错误机制。当多个线程对同一个集合的内容进行操作时,就可能会产生fail-fast事件。
例如:当某一个线程A通过iterator去遍历某集合的过程中,若该集合的内容被其他线程所改变了;那么线程A访问集合时,就会抛出ConcurrentModificationException异常,产生fail-fast事件。

(2)使用 CopyOnWriteArrayList ,在java.util.concurrent包下,多线程的时候使用,线程安全的!
将上面代码中的ArrayList换成CopyOnWirteArrayList也不会报错!

参考资料:
fail-fast 机制:http://www.cnblogs.com/skywang12345/p/3308762.html

Java中如何删除一个集合中的多个元素:http://www.importnew.com/20959.html


不管做什么,只要坚持下去就会看到不一样!在路上,不卑不亢!

Java中的`ConcurrentModificationException`通常发生在多线程环境下,当一个集合(如ArrayList、LinkedList等)在遍历时被其他线程修改了其内容,这将导致异常抛出,因为集合内部的数据结构已经被破坏,无法继续迭代。要避免这种异常,可以采取以下几种策略: 1. **同步访问**:在遍历集合的同时锁定它,确保在遍历期间不会发生改变。例如,你可以使用`synchronized`关键字或更推荐的`Collections.synchronizedList()`方法来同步列表。 ```java synchronized(list) { for (Element element : list) { // ...处理元素... } } ``` 2. **Copy-on-write模式**:如果集合支持并发访问并允许安全的复制,如`CopyOnWriteArrayList`,可以在遍历时创建一个副本,然后在副本上操作,原集合不会受影响。 ```java CopyOnWriteArrayList<Element> copy = new CopyOnWriteArrayList<>(list); for (Element element : copy) { // ...处理元素... } ``` 3. **观察者模式**:使用`java.util.Observable`和`java.util.Observer`来通知数据变化,而不是直接修改。观察者可以在更新后自行决定是否需要重新遍历。 4. **使用`Iterator`的try-with-resources语句**:`Iterator`有一个`hasNext()`和`next()`方法组合,可以确保在遇到异常时自动关闭迭代器。 ```java Iterator<Element> iterator = list.iterator(); while (iterator.hasNext()) { try { Element element = iterator.next(); // ...处理元素... } catch (ConcurrentModificationException e) { break; // 或者记录错误并退出 } } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值