List 递归删除元素java.util.ConcurrentModificationException

List 递归删除元素

在使用list迭代器移除元素的时候,如果存在递归调用就会报如下错

Exception in thread "main" java.util.ConcurrentModificationException
	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
	at java.util.ArrayList$Itr.next(ArrayList.java:851)
	at com.sl.jvm.dome.aop.jit.Test.test(Test.java:25)
	at com.sl.jvm.dome.aop.jit.Test.main(Test.java:15)

如下例子

public class Test {
    public static void main(String[] args){
       List<String> list = new ArrayList<>();
       list.add("a");
       list.add("b");
       list.add("b2");
       list.add("c");
       list.add("e");
       test(list);
    }

    private static void test(List<String> list) {
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()){
            String s = iterator.next();
            if("a".equals(s) || "c".equals(s)){
                iterator.remove();
            }
            if("b".equals(s)){
                iterator.remove();
                test(list);

            }
            if("e".equals(s)){
                break;
            }
        }
    }
}

运行就会报如上的错,这个错发生的地方在

final void checkForComodification() {
      if (modCount != expectedModCount)
      throw new ConcurrentModificationException();
 }

在list操作之前比如next, remove, add等操作都会调用checkForComodification方法。

modCount : 在创建list的初始化, 用来记录list的修改次数。添加,删除值都会+1.

expectedModCount : 在创建 迭代器的时候初始化,会把modCount的值复值给expectedModCount。

这两个值主要使用Fail-Fast 机制 ,在多线程的环境下防止有其他线程修改list中的数据。

在这里报ConcurrentModificationException错是因为递归的时候,这一次递归调用list.iterator()初始化了expectedModCount的值,在这次递归中修改了expectedModCount和modCount的值,这次递归处理完,回到上一次递归,但是上一次递归的expectedModCount的值没有涨上去,modCount的值已经涨上去了,导致modCount != expectedModCount


处理方法

目前有两种处理方法
1. 每次循环的时候刷新expectedModCount, 调用list.iterator()初始化expectedModCount。改成 如下

private static void test(List<String> list) {
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()){
            iterator = list.iterator();
            String s = iterator.next();
            if("a".equals(s) || "c".equals(s)){
                iterator.remove();
            }
            if("b".equals(s)){
                iterator.remove();
                test(list);

            }
            if("e".equals(s)){
                break;
            }
        }
    }

2.递归的时候传入Iterator, 不让其重新初始化,就能保持expectedModCount和modCount一致。 改成如下

private static void test(Iterator<String> iterator) {
        while (iterator.hasNext()){
            String s = iterator.next();
            if("a".equals(s) || "c".equals(s)){
                iterator.remove();
            }
            if("b".equals(s)){
                iterator.remove();
                test(iterator);

            }
            if("e".equals(s)){
                break;
            }
        }
    }

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值