【问题标题】:ConcurrentModificationException while trying to delete an item from ArrayList [duplicate]尝试从 ArrayList 中删除项目时出现 ConcurrentModificationException [重复]
【发布时间】:2019-05-12 15:24:54
【问题描述】:

实际上,在按下按钮后,我有一个方法可以检查我的 itemStorico ArrayList 中是否存在来自 itemModel 的新添加项目,然后如果该项目存在于名为 itemModel 的新列表中,我将从 itemStorico 中删除旧项目并添加新项目一,否则只是添加新项目而不删除旧项目。

但我收到以下错误:

2018-12-11 16:34:04.067 29033-29033/it.gabtamagnini.realco E/AndroidRuntime: FATAL EXCEPTION: main
    Process: it.gabtamagnini.realco, PID: 29033
    java.util.ConcurrentModificationException
        at java.util.ArrayList$Itr.next(ArrayList.java:831)
        at it.gabtamagnini.realco.OrdiniActivity.saveStorico(OrdiniActivity.java:1396)
        at it.gabtamagnini.realco.OrdiniActivity$29.onClick(OrdiniActivity.java:1368)
        at android.view.View.performClick(View.java:5637)
        at android.view.View$PerformClick.run(View.java:22433)
        at android.os.Handler.handleCallback(Handler.java:751)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6130)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)

虽然这里是我的方法中的代码:

 for(ItemModel itemModels : itemModel){
            boolean exist = false;
            for(ItemModel itemModel2 : itemStorico){
                if(itemModels.getCodiceArticolo().contains(itemModel2.getCodiceArticolo())) {
                    itemStorico.remove(itemModel2);
                    itemStorico.add(itemModels);
                    exist = true;
                }
            }
            if(!exist) {
                itemStorico.add(itemModels);
            }
        }

【问题讨论】:

    标签: android arraylist


    【解决方案1】:

    您不能从“for-each”循环(for (item : collection) 结构)内部调用 remove()。这样做会抛出ConcurrentModificationException

    如果你想在循环时循环和删除项目,你可以使用传统的“for”循环:

    for (int i = 0; i < itemStorico.size(); ++i) {
        ItemModel itemModel2 = itemStorico.get(i);
        if (...) {
            itemStorico.remove(i);
            ...
        }
    }
    

    但是,这会引入一个微妙的错误。想象一下,您正在循环访问 [a,b,c,d]。如果您位于索引 1 并从集合中删除 b,则所有内容都会“滑过”并且您将拥有 [a,c,d]。下次查看索引 2 时,您将跳过 c

    你可以通过在删除时手动递减索引来避免该错误,但这有点恶心。

    ...
        itemStorico.remove(i);
        --i;
    ...
    

    您也可以通过使用集合的iterator() 来完全避免该问题。

    for (Iterator<ItemModel> iterator = itemStorico.iterator(); iterator.hasNext(); ) {
        ItemModel itemModel2 = iterator.next();
        if (...) {
            iterator.remove();
            ...
        }
    }
    

    【讨论】:

    • 我可以用迭代器添加项目还是直接删除它?
    • 如果您使用ListIterator&lt;ItemModel&gt; iterator = itemStorico.listIterator()(假设itemStoricoList 而不是Set 等),那么可以。
    【解决方案2】:
    for(ItemModel itemModel2 : itemStorico){
                if(itemModels.getCodiceArticolo().contains(itemModel2.getCodiceArticolo())) {
                    itemStorico.remove(itemModel2);
    

    您正在从列表中删除一个元素,同时迭代它。你不能!

    为避免此并发问题,您可以使用迭代器,但请查看此答案以解释您需要知道的所有内容:Remove elements from collection while iterating

    【讨论】:

      猜你喜欢
      • 2020-11-05
      • 2013-12-14
      • 2021-12-15
      • 1970-01-01
      • 2014-06-03
      • 2018-01-09
      • 2013-03-29
      • 1970-01-01
      • 2013-03-02
      相关资源
      最近更新 更多