简体   繁体   English

Java:替换ArrayList中的模式时,并发修改异常

[英]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). 我正在做一个压缩文件的程序(表示为Byte的ArrayList),有时我必须将所有出现的预定义“字符串”替换为一个字节(“ string”作为字节序列) ,而不是Java语言中的字符串)。

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 字节类型ArrayList的“预定义字符串”存储在变量opt_word中,其长度存储在变量opt_length中,且始终> = 2

I am getting a Concurrent Modifiation exception at the place noted "HERE". 我在标为“ 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. remove()方法更改Arraylist的大小。 Changing the Arraylist size while iterating through it causes the Concurrent Modification Error you mentioned. 在迭代过程中更改Arraylist大小会导致您提到的并发修改错误。 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. 解决方案是跟踪要在其他列表上删除的项目,然后在for循环完成后将其删除。

@David Pitre has already pointed out the problem. @David Pitre已经指出了问题。 Change the ArrayList to CopyOnWriteArrayList 将ArrayList更改为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);
    }
}
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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