在遍历 ArrayList 时获取 java.util.ConcurrentModificationException

Posted

技术标签:

【中文标题】在遍历 ArrayList 时获取 java.util.ConcurrentModificationException【英文标题】:Getting java.util.ConcurrentModificationException while looping through ArrayList 【发布时间】:2021-09-19 22:07:27 【问题描述】:

我正在开发一个使用 Spring Boot 作为后端的应用程序。在循环并更新 Array 列表中的对象的值时抛出以下错误,

java.util.ConcurrentModificationException: null
        at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:911) ~[na:1.8.0_292]
        at java.util.ArrayList$Itr.next(ArrayList.java:861) ~[na:1.8.0_292]
        at org.hibernate.collection.internal.AbstractPersistentCollection$IteratorProxy.next(AbstractPersistentCollection.java:883) ~[hibernate-core-5.4.12.Final.jar!/:5.4.12.Final]
   

我已经改变了如下循环,

for(Object obj : myObjectList) 
   obj.setEndDate(someDate);
   obj.isActive(false);
   objectRepository.save(obj);

Iterator<Object> objIterator = myObjectList.iterator();
   while(objIterator.hasNext()) 
      Object obj = objIterator.next();
      obj.setEndDate(someDate);
      obj.isActive(false);
      objectRepository.save(obj);
   

两者都抛出相同的错误。

在将日志打印到这些 for 循环中时。它将第一次打印日志并在第二次迭代时抛出错误。

【问题讨论】:

objectRepository.save(object) 是做什么的?如果这也改变了列表,那么将抛出异常。 object 是什么?我假设objectRepository.save(object);objectRepository.save(obj); 感谢您指出@GauthamM。 这个应用程序是多线程的吗?在您迭代 myObjectList 时,是否有其他线程正在修改它? 没有堆栈跟踪吗? 【参考方案1】:

如果你想在迭代列表的同时修改它,切换到使用 Iterator 是正确的调用,但是你需要一个 while 循环而不是 for 循环:

List<Object> myObjectList = new ArrayList<>();
    Iterator<Object> objIterator = myObjectList.iterator();
    while (objIterator.hasNext()) 
        Object obj = objIterator.next();
        obj.setEndDate(someDate);
        obj.isActive(false);
        objectRepository.save(obj);
    

【讨论】:

【参考方案2】:

您可以通过像这样创建新的 ArrayList 包装器来使用故障安全交互:

for(Object obj : new ArrayList<>(myObjectList)) 
   obj.setEndDate(someDate);
   obj.isActive(false);
   objectRepository.save(obj);

它会解决你的问题

【讨论】:

【参考方案3】:

补充其他答案,您可以先修改您的收藏然后保存。

    myObjectList.forEach(obj -> 
        obj.setEndDate(someDate);
        obj.isActive(false);
    );
    objectRepository.save(myObjectList); //Depending of your version, this method could be saveAll();

【讨论】:

以上是关于在遍历 ArrayList 时获取 java.util.ConcurrentModificationException的主要内容,如果未能解决你的问题,请参考以下文章

在Java中遍历父类的ArrayList时使用Subclass方法

获取 ArrayList 值并将其设置为按钮单击时的 TextView 不工作 - RecyclerView

Java中 ArrayList类常用方法和遍历

ArrayList集合的特点和几种遍历方法

arraylist 为什么 删除元素时要使用迭代器而不能使用遍历

Java中ArrayList边遍历边修改