在 java 中使用另一个 ArrayList 更新 ArrayList

Update ArrayList using another ArrayList in java

我发现了很多关于 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);
    }
}

这段代码应该在哪里 return:

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

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

而是 returning:

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

for (Object a : changedArr)

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

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

您正在修改 ArrayList changedArr,同时使用增强的 for 循环迭代它。这会导致抛出 ConcurrentModificationException,因为增强的 for 循环会为循环生成迭代器,并且迭代器假定列表在迭代器的生命周期内不会被修改。如果您在迭代器迭代列表时修改列表,那么您将得到一个 ConcurrentModificationException。

一个解决方案是拥有一个原始列表和一个副本,并且只修改副本。在遍历列表时永远不要修改列表。

像这样更改您的代码:

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);
        }
    }

A​​ ConcurrentModificationException 被抛出,因为你在修改 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.
    }
}

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

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

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);
    }
}