1

I've come across a lot of information on ArrayLists and how to manipulate them but nothing seems to be answering my issue.

I want to check if an element in an arraylist is not alive, and if so remove it but add another 2 to the list. Usually quite easy except that I need to then add the changes to another arraylist that contains all the elements in the first arraylist as well as elements from other external arraylists.

I thought Id be able to do this using a temp arraylist as shown below:

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

Where this code should 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]

It's instead 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

So my question is, what am I doing wrong to cause these errors? Is this method possible? If not, I don't see why, could you explain? And how could I get around it?

If you've made it this far, thanks for taking the time to read my ramblings! :D

5 Answers 5

1

You are modifying your ArrayList changedArr while iterating over it using an enhanced for loop. This causes a ConcurrentModificationException to be thrown because enhanced for loops produce iterators for the looping to occur, and iterators assume that the list will not me modified during the iterator's lifetime. If you modify a list while an iterator is iterating over it then you will get a ConcurrentModificationException.

A solution would be to have an original list and a copy and only modify the copy. You should never modify a list while you are iterating over it.

Sign up to request clarification or add additional context in comments.

Comments

0

Change your code like this:

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

Comments

0
for (Object a : changedArr)

creates an implicit iterator on the list. If you modify the list then the next iteration will fail.

Try a normal for loop using indices. This should help you around the exception

Comments

0

A ConcurrentModificationException is thrown because you're modifying changedArr while iterating over it. The iterator notices these changes and throws an exception. A very clear and easy way you could solve this, is by using a 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.
    }
}

Comments

0

Thanks a lot for your advice @Max Weinzierl, worked brilliantly! I added an 'addedArr' array to use as a middle-man.

For anyone who might have a similar issue, here's the re-jigged code:

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.