当我尝试使用迭代器编辑ArrayList时出现ConcurrentModificationException

时间:2018-03-17 22:13:16

标签: java android arrays

我有一个Object的ArrayList,我正在尝试编辑其中一个对象的字段,但是当我这样做时,我收到了ConcurrentModificationException。我已经读过我需要使用Iterator,但即便如此,我仍然收到错误消息。

我的代码:

if(summedEmotionValuesArrayList.size() == 0){
    summedEmotionValuesArrayList.add(newEmotionValuesDataset);
}else {
    for (Iterator<EmotionValuesDataset> currentEmotionValuesDataset = summedEmotionValuesArrayList.iterator(); currentEmotionValuesDataset.hasNext(); ) {
        EmotionValuesDataset emotionValuesDataset = currentEmotionValuesDataset.next();
        if (emotionValuesDataset.getEmotionName().equals(newEmotionValuesDataset.getEmotionName())) {
            double newValue = emotionValuesDataset.getEmotionValue() + newEmotionValuesDataset.getEmotionValue();
            emotionValuesDataset.setEmotion_value(newValue);
        } else {
            summedEmotionValuesArrayList.add(newEmotionValuesDataset);
        }
    }
}

此代码在for循环中执行多次。此行发生错误消息

  

EmotionValuesDataset emotionValuesDataset = currentEmotionValuesDataset.next();

非常感谢任何帮助。

3 个答案:

答案 0 :(得分:2)

summedEmotionValuesArrayList.add(newEmotionValuesDataset);

这行产生问题,你应该创建一些其他列表(将其命名为yourTempList)并在那里添加元素,在退出for循环之后只需使用

summedEmotionValuesArrayList.addAll(yourTempList)

答案 1 :(得分:2)

您正尝试将值基本上添加到arraylist summedEmotionValuesArrayList。如果您研究add的实施方式,

    public void add(E e) {
        checkForComodification();

        try {
            int i = cursor;
            ArrayList.this.add(i, e);
            cursor = i + 1;
            lastRet = -1;
            expectedModCount = modCount;
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    }

而且,如果你看一下checkForComodification()的实现,你可以看到它检查modCount

因此,基于此以及https://docs.oracle.com/javase/9/docs/api/java/util/AbstractList.html的文档,您可以看到以下内容。

  

如果此字段的值意外更改,则为迭代器(或列表)   迭代器)会抛出一个ConcurrentModificationException来响应   下一步,删除,上一步,设置或添加操作。这提供了   失败的行为,而不是面部的非确定性行为   迭代期间的并发修改。

因此,您可以通过创建新的临时列表来解决此问题。这已经得到了解答。无论如何,

    ArrayList<EmotionValuesDataset> tempList = new ArrayList();

    for(...){
        //use your logic, but instead of  summedEmotionValuesArrayList.add(newEmotionValuesDataset);
        tempList.add(newEmotionValuesDataset);

    }

    //outside of forloop
    summedEmotionValuesArrayList.addAll(tempList)

我希望它有所帮助!

答案 2 :(得分:1)

迭代ArrayList时,迭代器始终将modCount检查为迭代开始时保存的值。此值随每次添加,删除,设置......而变化,如果在迭代期间发生变化,则会抛出ConcurrentModificationException

如果要删除当前所在的项目,可以使用Iterator #remove方法,该方法知道更新了expectedModCount。在向ArrayList添加值时,可以将它们保存在临时列表中,然后在迭代结束时将所有这些元素添加到原始列表中。

for(...) {
    ...
    temp.add(newValue);
    ...
}
summedEmotionValuesArrayList.addAll(temp);