简体   繁体   中英

Java : Concurrent Modification exception when replacing pattern in ArrayList

I am doing a program to compress a file (which is represented as an ArrayList of Byte ) and at some point I have to replace all occurrences of a pre-defined "string" by a single byte("string" as a sequence of bytes, not a String in the Java language).

The "pre-defined string" of type ArrayList of Byte is stored in the variable opt_word, and its length is stored in the variable opt_length, and is always >=2

I am getting a Concurrent Modifiation exception at the place noted "HERE". Further debugging showed me that the exception happens on the loop iteration right after the first replacement.

I know other people asked about similar issues like here and here , but my case is quite different from theirs. I use a standard for loop.

            CopyOnWriteArrayList<Integer> removal_indexes = new CopyOnWriteArrayList<Integer>();
            for(int j=0, l=0; j <= encoded.get(k).size() - opt_length; ++j, ++l)
            {
                List<Byte> str = encoded.get(k).subList(j, j + opt_length);
                if (str.equals(opt_word))  // <-- here
                {
                    removal_indexes.add(l);
                    j += opt_length - 1;
                }
            }

            for(int l=0; l < removal_indexes.size(); ++l)
            {
                encoded.get(k).set(removal_indexes.get(l), (byte)(lowr + lengths.size()));
                for(int i=1; i < opt_length; ++i)
                    encoded.get(k).remove(removal_indexes.get(l)+1);
            }

This is the same situation as the others you linked to. The remove() method changes the size of the Arraylist. Changing the Arraylist size while iterating through it causes the Concurrent Modification Error you mentioned. The solution is to keep track of the items to remove on some other list and then remove them after the for loop is finished.

@David Pitre has already pointed out the problem. Change the ArrayList to CopyOnWriteArrayList

Update:

I tried doing what you wanted to do, ie, search and replace and it worked for me. I implemented a sample code. See if it works for you.

public class Search {
List<Byte> fileToCompress;  // Your File
List<Byte> opt_word = new ArrayList<Byte>(); // "String" to search for in the "fileToCompress"
Byte replacement; // Replacement for "String"

public static void main(String args[]) {
    Search s = new Search();

    s.display();
    s.findAndReplace();
    System.out.println("_____________________");
    s.display();
}

public Search() {
    fileToCompress = new CopyOnWriteArrayList<Byte>();

    fileToCompress.add((byte)1);
    fileToCompress.add((byte)3);
    fileToCompress.add((byte)3);
    fileToCompress.add((byte)4);
    fileToCompress.add((byte)5);
    fileToCompress.add((byte)3);
    fileToCompress.add((byte)4);
    fileToCompress.add((byte)6);

    opt_word = new ArrayList<Byte>();

    opt_word.add((byte)3);
    opt_word.add((byte)4);

    replacement = new Byte((byte)0);
}

public void findAndReplace() {
    for(int i=0; i<fileToCompress.size(); i++) {
        boolean isFound = false;
        if(fileToCompress.get(i).equals(opt_word.get(0))) {
            isFound = checkMatch(i);
            if(isFound) {
                replace(i);
            }
        }
    }
}

private boolean checkMatch(int index) {
    boolean isFound = true;
    for(int i=0; i<opt_word.size(); i++) {
        if(!opt_word.get(i).equals(fileToCompress.get(index + i))) {
            isFound = false;
            break;
        }
    }
    return isFound;
}

private void replace(int index) {
    for(int i=0 ; i<opt_word.size(); i++) {
        fileToCompress.remove(index);
    }

    fileToCompress.add(index, replacement);
}

public void display() {
    for(Byte b : fileToCompress) {
        System.out.println(b);
    }
}
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM