Featured image of post 對遍歷中的集合類修改,會有什麼樣的問題呢

對遍歷中的集合類修改,會有什麼樣的問題呢

哇操!這什麼問題啊?淺談Java中的ConcurrentModificationException

前言

前一陣子面試了一家博奕業,他的第一題是這樣的

給一整數陣列,並把陣列中的0移到最後,其餘的數字保持原來的順序。 例如輸入陣列{0,0,0,1,2,3,4,5,6,7,8}, (你不知道index) 請寫個方法可輸出為{1,2,3,4,5,6,7,8,0,0,0}

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
   public static void main(String[] args) {
        List<Integer> numbList = new ArrayList<>(Arrays.asList(0,0,0,1,2,3,4,5,6,7,8));
        List<Integer> numbList2 = new ArrayList<>();
        for(Integer num :numbList){
            if(num == 0){
                /**
                 * TODO
                 * 尝试完成把 List中的0移到最後
                 */
                numbList.remove(num);
                numbList2.add(num);
            }
        }
        System.out.println(numbList);
    }

至於具體來說到底要怎麼寫不是我想討論的重點,而是這題藏在魔鬼裡的細節

ConcurrentModificationException

im-a-little-confused

當你實際執行後就會出現這個錯誤ConcurrentModificationException

image-20230723152310712

他說錯誤出現在第12行,但實際上錯誤並不是出現在第12行,應該是在第18行的位置,我們可以開Debugger,看起來會更明顯一點

demo

他回報了這個錯誤,那這個錯誤具體而言是什麼呢?

ConcurrentModificationException這個錯誤會發生在對遍歷的集合類進行刪除、增加時會出現這個併發修改錯誤,而會拋出這個錯誤的原因是因為

image-20230723153232134

集合類中的modCount跟expectModCount不相等而拋出的,由於本人才疏學淺,目前理解的概念像是這樣

因為Java常見的集合類本身並不是執行緒安全(Thread Safe)的,因此會有兩個int,expectModCount像是去紀錄理論的修改次數,modCount像是去記錄實際修改的次數,當兩邊的數字Match不起來,就會拋出錯誤,提醒你因為執行緒不安全的關係導致你執行的結果會與預期有落差,這樣的行為也稱之為Fast-Fail,

image-20230723154447030

(圖片來自於網路)

因為在remove這邊有modCount++的行為,導致兩邊值不同,因而拋出錯誤

參考連結

https://cloud.tencent.com/developer/article/1896820

Licensed under CC BY-NC-SA 4.0