1. 程式人生 > 其它 >java list只有兩個元素時,迴圈刪除(remove)元素不會報ConcurrentModificationException異常

java list只有兩個元素時,迴圈刪除(remove)元素不會報ConcurrentModificationException異常

技術標籤:java

我們都知道,java中的ArrayList在使用增強for迴圈或iterator迴圈中呼叫list本身的remove方法刪除元素時會報ConcurrentModificationException異常,通過iterator的remove方法來刪除就不會報異常了。當然增強for迴圈只是個語法糖,本質還是用的iterator。今天想試驗一下這個異常,於是寫了如下程式碼。

public static void main(String[] args) {
    List<String> list = new ArrayList<>();
    list.add("abc");
    list.add("123");
    System.out.println(list);
    Iterator<String> iterator = list.iterator();
    while (iterator.hasNext()) {
        String next = iterator.next();
        list.remove(next);
    }
    System.out.println(list);
}

結果輸出如下,並沒有報錯,這就奇怪了,不是說在迴圈中呼叫list的remove方法會異常嗎,為什麼沒有呢?如果我把list的元素個數改成3個,就會報異常了,原因的話看一下原始碼就知道了。

導致這個現象的原因和hasNext()方法有關係,看一下hasNext()原始碼,cursor是當前遍歷到的元素下標,每當我們呼叫iterator.next()方法時,這個cursor就會加1,當cursor的大小和list中的size一樣時,說明遍歷到陣列尾部了,就沒有元素了,hasNext()就會返回false。

接下來分析我們上面的程式,迴圈開始前,cursor=0,不等於size的大小2,進入迴圈,呼叫next()方法,呼叫next()方法時會呼叫checkForComodification(),也就是判斷一下在迴圈過程中list是否被改變過,由於我們第一次迴圈,還沒有對list做過改變,所以next可以正常返回。返回下標0處的"abc",此時cursor被置為了1,再呼叫remove方法,此時list中就只有“123”這個元素了,size為1。

再次迴圈,由於此時cursor為1,我們remove了一個元素後,list的size也變為了1,所以hasNext()判斷為false了,就跳出迴圈了,然後程式結束。

也就是說,雖然我們list中有兩個元素,但是實際上for迴圈只進行了一次,只把“abc”元素給刪除了。所以會出現上面的現象。

如果list中的元素是1個,3個或更多,則會報ConcurrentModificationException異常。所以平時還是不要用這種方式刪除list中的元素。