天天看點

java.util.ConcurrentModificationException: null異常

作者:你可以叫我老白

創作背景:在加強for循環中使用了remove操作

原因:

在官方文檔中ConcurrentModificationException的介紹如下:

public class ConcurrentModificationException extends RuntimeException

某個線程在 Collection 上進行周遊時,通常不允許其他線程修改該 Collection,這會導緻周遊的結果是不确定的。當方法檢測到集合發生并發修改時,不允許這種修改,抛出此異常。

在執行增删操作以後,集合的expectedModCount和modCount的值不一緻,這兩個變量的作用都是記錄修改次數的,二者不相等,就會抛錯。

expectedModCount:表示對ArrayList修改次數的期望值,它的初始值為modCount。

modCount是AbstractList類中的一個成員變量。

先說解決方法:

使用增強for循環周遊,增删操作使用疊代器實作。原因我們後面說,沒空看的直接看到測試代碼就可以了,先把工作解決了。

實戰代碼實作:

//先保證兩個集合有值,LinkedList可以,這裡省略指派步驟
LinkedList<PlayAudioEntity> audioList = new LinkedList<>();
LinkedList<PlayAudioEntity> resultList = new LinkedList<>();

//入棧,redis有資料則需要比較是否有相同專輯下同一作品,有則放入隊頭
        for (PlayAudioEntity entity : audioList) {
            if (!CollectionUtils.isEmpty(resultList)) {
                String audioId = entity.getAudioId();
            
                //使用疊代器删除資料
                Iterator<PlayAudioEntity> it = resultList.iterator();
                while (it.hasNext()) {
                    PlayAudioEntity entity2 = it.next();
                    String audioId2 = entity2.getAudioId();
                    if (audioId2.equals(audioId)) {
                        it.remove();
                    }
                }
            }
          
            resultList.push(entity);
        }           

看不懂的看這裡,測試代碼和結果:

public static void main(String[] args) {
    //指派
    LinkedList<TestDO> resultList = new LinkedList<>();
    TestDO testDO1 = new TestDO();
    testDO1.setId(1);
    testDO1.setName("名字1");
    TestDO testDO2 = new TestDO();
    testDO2.setId(2);
    testDO2.setName("名字2");
    TestDO testDO3 = new TestDO();
    testDO3.setId(3);
    testDO3.setName("名字3");
    TestDO testDO4 = new TestDO();
    TestDO testDO5 = new TestDO();
    testDO4.setId(4);
    testDO4.setName("名字4");
    testDO5.setId(5);
    testDO5.setName("名字5");
    resultList.add(testDO1);
    resultList.add(testDO2);
    resultList.add(testDO3);
    resultList.add(testDO4);
    resultList.add(testDO5);

    //LinkedList<TestDO> resultList2 = resultList;
    //resultList.removeIf(a-> a.getId()==2);

    System.out.println("resultList:" + resultList);
    //System.out.println("resultList2:" + resultList2);
    System.out.println("完畢");




    //使用疊代器删除資料
    /*Iterator<TestDO> it = resultList.iterator();
    while (it.hasNext()) {
        TestDO entity2 = it.next();
        Integer audioId2 = entity2.getId();
        if (audioId2 == 2) {
            it.remove();
        }
    }

    System.out.println("resultList:" + resultList);*/


    //使用普通for循環删除資料
    /*for (int i = 0; i < resultList2.size(); i++) {
        TestDO testDO = resultList2.get(i);
        Integer id = testDO.getId();
        if (id == 3) {
            resultList2.remove(testDO);
        }
    }*/

   // System.out.println("resultList:" + resultList2);
}           

1.疊代器

java.util.ConcurrentModificationException: null異常

2.stream

java.util.ConcurrentModificationException: null異常

3.還有一種網上方法叫使用索引(普通for循環)周遊。用了用,結果是隻能是ArrayList才可以使用。普通for循環删除元素存在一個問題,那就是remove操作會改變List中元素的下标,可能存在漏删的情況。是以建議使用疊代器删除。

java.util.ConcurrentModificationException: null異常

有時間的話會在研究下問什麼不允許加強for循環删除的,懂得大佬也可以在下面評論指正。

創作不易,如果這篇文章對你有用,請點贊。有其他建議請在下方留言評論,謝謝♪(・ω・)ノ!

java.util.ConcurrentModificationException: null異常