1

我遇到了很多关于 ArrayLists 以及如何操作它们的信息,但似乎没有什么能回答我的问题。

我想检查 arraylist 中的元素是否不存在,如果是,则将其删除,但将另一个 2 添加到列表中。通常很容易,除了我需要将更改添加到另一个数组列表中,该数组列表包含第一个数组列表中的所有元素以及来自其他外部数组列表的元素。

我认为我可以使用临时数组列表来做到这一点,如下所示:

import java.util.ArrayList;

public class main {

    public static ArrayList<String> changedArr = new ArrayList(){ {add("M1"); add("alive"); add("M3");} };
    public static ArrayList<String> tempArr = new ArrayList();
    public static ArrayList<String> totalArr = new ArrayList(){ {add("M1"); add("alive"); add("M3"); add("L4"); add("S5");} };

    public static void main(String[] args) {

        System.out.println("changedArray = "+changedArr);
        System.out.println("tempArray = "+tempArr);
        System.out.println("totalArray = "+totalArr);

        for(Object a : changedArr){
            if(a !="alive") {
                tempArr.clear();
                changedArr.remove(a);
                totalArr.remove(a);
                tempArr.add("S6");
                tempArr.add("S7");
                changedArr.addAll(tempArr);
                totalArr.addAll(tempArr);
            }
        }
        System.out.println("\nchangedArray = "+changedArr);
        System.out.println("tempArray = "+tempArr);
        System.out.println("totalArray = "+totalArr);
    }
}

此代码应返回的位置:

changedArray = [M1, alive, M3]
tempArray = []
totalArray = [M1, alive, M3, L4, S5]

changedArray = [alive, S6, S7]
tempArray = [S6, S7]
totalArray = [alive, L4, S5, S6, S7]

相反,它返回:

Exception in thread "main" java.util.ConcurrentModificationException
changedArray = [M1, M2, M3]
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
tempArray = []
    at java.util.ArrayList$Itr.next(ArrayList.java:851)
totalArray = [M1, M2, M3, L4, S5]
    at main.main(main.java:31)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

Process finished with exit code 1

所以我的问题是,我做错了什么导致这些错误?这种方法可行吗?如果不是,我不明白为什么,你能解释一下吗?我怎么能绕过它?

如果您已经做到了这一点,感谢您花时间阅读我的漫谈!:D

4

5 回答 5

1

您正在修改 ArrayList changedArr,同时使用增强的 for 循环对其进行迭代。这会导致引发 ConcurrentModificationException,因为增强的 for 循环会生成迭代器以使循环发生,并且迭代器假定在迭代器的生命周期内不会修改列表。如果您在迭代器对其进行迭代时修改列表,那么您将收到 ConcurrentModificationException。

一个解决方案是拥有一个原始列表和一个副本,并且只修改副本。在迭代列表时,您永远不应该修改它。

于 2017-03-04T22:36:25.270 回答
0

像这样更改您的代码:

List<Object> copy = changedArr.stream().collect(Collectors.toList());

    for (Object a : copy) {
        if (a != "alive") {
            tempArr.clear();
            changedArr.remove(a);
            totalArr.remove(a);
            tempArr.add("S6");
            tempArr.add("S7");
            changedArr.addAll(tempArr);
            totalArr.addAll(tempArr);
        }
    }
于 2017-03-04T22:39:19.257 回答
0
for (Object a : changedArr)

在列表上创建一个隐式迭代器。如果您修改列表,则下一次迭代将失败。

尝试使用索引进行正常的 for 循环。这应该可以帮助您解决异常

于 2017-03-04T22:34:38.940 回答
0

抛出AConcurrentModificationException是因为您在changedArr迭代它时正在修改它。迭代器注意到这些变化并抛出异常。您可以解决此问题的一种非常清晰且简单的方法是使用ListIterator

ListIterator iterator = changedArr.listIterator();
while (iterator.hasNext()) {
    Object a = iterator.next();
    if (a != "alive") {
        iterator.remove(); // removes 'a' from changedArr
        iterator.add("S6"); // adds "S6" to changedArr
        iterator.add("S7");
        // etc.
    }
}
于 2017-03-04T22:47:38.110 回答
0

非常感谢您的建议@Max Weinzierl,工作出色!我添加了一个“addArr”数组用作中间人。

对于任何可能有类似问题的人,这里是重新调整的代码:

import java.util.ArrayList;

public class main {

    public static ArrayList<String> changedArr = new ArrayList(){ {add("M1"); add("alive"); add("M3");} };
    public static ArrayList<String> addedArr = new ArrayList();//----- New ArrayList 'addedArr' used for adding the new elements
    public static ArrayList<String> tempArr = new ArrayList();
    public static ArrayList<String> totalArr = new ArrayList(){ {add("M1"); add("alive"); add("M3"); add("L4"); add("S5");} };

    public static void main(String[] args) {
        tempArr.addAll(changedArr);//--------------------------------- Duplicated changedArr
        System.out.println("addedArray = "+addedArr);
        System.out.println("tempArray = "+tempArr);
        System.out.println("changedArray = "+changedArr);
        System.out.println("totalArray = "+totalArr+"\n");
        int counter = 0;//-------------------------------------------- Counter to increment the added elements

        for(Object a : changedArr){
            addedArr.clear();//--------------------------------------- Make sure 'addedArr' is cleared at start of each loop
            if(a !="alive") {
                tempArr.remove(a);
                totalArr.remove(a);
                addedArr.add("S"+(6+counter));
                counter++;
                addedArr.add("S"+(6+counter));
                counter++;
                tempArr.addAll(addedArr);//--------------------------- Adds new elements to tempArr to be added to changedArr
                totalArr.addAll(addedArr);//-------------------------- Adds new elements to totalArr
            }
            System.out.println("addedArray = "+addedArr);
        }
        changedArr.clear();//----------------------------------------- Clear changedArr to make sure that anything removed in the loop is removed
        changedArr.addAll(tempArr);//--------------------------------- Add all changes from tempArr to changedArr
        System.out.println("\ntempArray = "+tempArr);
        System.out.println("changedArray = "+changedArr);
        System.out.println("totalArray = "+totalArr);
    }
}
于 2017-03-05T00:05:16.740 回答