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



我正在执行一个压缩文件的程序(表示为字节的ArrayList),在某个时刻,我必须用一个字节("字符串"是字节序列,而不是Java语言中的字符串)替换预定义的"字符串"的所有出现。

Byte的ArrayList类型的"预定义字符串"存储在变量opt_word中,其长度存储在变量pti_length中,并且始终>=2

我在标有"此处"的位置收到了并发修改异常。进一步的调试表明,异常发生在第一次替换之后的循环迭代中。

我知道其他人问过类似的问题,比如这里和这里,但我的情况与他们的情况大不相同。我使用循环的标准。

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

这与您链接到的其他对象的情况相同。remove()方法会更改Arraylist的大小。在遍历数组列表时更改其大小会导致您提到的并发修改错误。解决方案是跟踪其他列表中要删除的项目,然后在for循环完成后将其删除。

@David Pitre已经指出了这个问题。将ArrayList更改为CopyOnWriteArrayList

更新:

我试着做你想做的事情,即搜索和替换,这对我很有效。我实现了一个示例代码。看看它是否适合你。

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

最新更新