摘要:單線程的迭代過程中刪除集合元素以上代碼會出現如下異常從后往前看第行代碼我們在執行代碼行時調用了這個是調用返回的對象這個對象的方法如下圖方法首先它會調用這個方法這個方法很簡單就是比較這兩個值是不是相等不相等就拋出異常如下圖這兩個值為什么會不相
單線程的Iterator迭代過程中刪除集合元素
public class TestIterator { public static void main(String[] args) { Listlist = new ArrayList<>(); list.add("1"); list.add("2"); list.add("3"); list.add("4"); list.add("5"); list.add("6"); Iterator it = list.iterator(); while (it.hasNext()) { String next = it.next(); if("3".equals(next)) { list.remove(3); } System.out.println(next); } } }
以上代碼會出現如下異常
Exception in thread "main" java.util.ConcurrentModificationException at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901) at java.util.ArrayList$Itr.next(ArrayList.java:851) at caoyan.test.TestIterator.main(TestIterator.java:22)
從后往前看:
TestIterator第22行代碼:
String next = it.next();
我們在執行代碼22行時調用了it.next();這個it是ArrayList調用iterator()返回的對象;這個對象的next()方法如下圖:
public E next() { checkForComodification(); ...
next()方法首先它會調用checkForComodification()這個方法,這個方法很簡單,就是比較expectedModCount , modCount 這兩個值是不是相等;不相等就拋出異常;如下圖:
final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); }
這兩個值為什么會不相等,它們各自代表什么含義呢,我們看ArrayList的iterator()方法:
public Iteratoriterator() { return new Itr(); } /** * An optimized version of AbstractList.Itr */ private class Itr implements Iterator { int cursor; // index of next element to return int lastRet = -1; // index of last element returned; -1 if no such int expectedModCount = modCount;
Arraylist的iterator()方法,直接創建了一個私有的內部類Itr的對象;expectedModCount 就是定義在這個Itr中的成員變量,而且,在初始化的時候,將modCount賦值給expectedModCount,說明在剛生成Iterator的時候這兩個值是相等的.modCount是定義在哪里呢,看下面源碼
public class ArrayListextends AbstractList ... protected transient int modCount = 0;
modCount是AbstractList的成員變量,ArrayList繼承下來了.所以modCount代表ArrayList的實際長度.
當我們在iterator的迭代過程中改變了ArrayList的長度,就導致modCount變了,而expectedModCount 沒有變,導致不相等報錯
可是為什么用iterator的remove方法就不報錯呢,我們看Remove方法():
public void remove() { if (lastRet < 0) throw new IllegalStateException(); checkForComodification(); try { ArrayList.this.remove(lastRet); cursor = lastRet; lastRet = -1; expectedModCount = modCount; } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } }
可以看到,ArrayList在刪除元素后,expectedModCount = modCount;重新賦值,讓這兩個值相等了.所以,remove方法不會拋出這個異常
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/67499.html
摘要:單線程的迭代過程中刪除集合元素以上代碼會出現如下異常從后往前看第行代碼我們在執行代碼行時調用了這個是調用返回的對象這個對象的方法如下圖方法首先它會調用這個方法這個方法很簡單就是比較這兩個值是不是相等不相等就拋出異常如下圖這兩個值為什么會不相 單線程的Iterator迭代過程中刪除集合元素 public class TestIterator { public static voi...
摘要:單線程的迭代過程中刪除集合元素以上代碼會出現如下異常從后往前看第行代碼我們在執行代碼行時調用了這個是調用返回的對象這個對象的方法如下圖方法首先它會調用這個方法這個方法很簡單就是比較這兩個值是不是相等不相等就拋出異常如下圖這兩個值為什么會不相 單線程的Iterator迭代過程中刪除集合元素 public class TestIterator { public static voi...
摘要:迭代器智能嗎第一步,將列表中的根節點找出來。源碼翻開中迭代器的源碼。在迭代器對象執行操作之前,都會執行方法,以判斷當前操作下是否安全。 引言 ConcurrentModificationException這個異常大家都很熟悉,當在forEach進行刪除時都會出現該異常。 如果你還不了解,請參考澍澍的博客:關于在list循環的過程中進行刪除的處理 - 晨澍的博客 showImg(http...
摘要:迭代器智能嗎第一步,將列表中的根節點找出來。源碼翻開中迭代器的源碼。在迭代器對象執行操作之前,都會執行方法,以判斷當前操作下是否安全。 引言 ConcurrentModificationException這個異常大家都很熟悉,當在forEach進行刪除時都會出現該異常。 如果你還不了解,請參考澍澍的博客:關于在list循環的過程中進行刪除的處理 - 晨澍的博客 showImg(http...
摘要:源碼分析構造方法有兩個構造方法,一個是無參,另一個需傳入初始容量值。所以我們可以把上面的代碼轉換一下,等價于下面形式這個時候,我們再去分析一下的迭代器源碼就能找出原因。原因是刪除元素后,元素計數器,而迭代器中的也等于,從而導致返回。 1.概述 ArrayList 是一種變長的集合類,基于定長數組實現。ArrayList 允許空值和重復元素,當往 ArrayList 中添加的元素數量大于...
閱讀 3868·2021-09-10 11:22
閱讀 2324·2021-09-03 10:30
閱讀 3659·2019-08-30 15:55
閱讀 1870·2019-08-30 15:44
閱讀 839·2019-08-30 15:44
閱讀 581·2019-08-30 14:04
閱讀 3041·2019-08-29 17:18
閱讀 1262·2019-08-29 15:04