摘要:單線程的迭代過程中刪除集合元素以上代碼會出現(xiàn)如下異常從后往前看第行代碼我們在執(zhí)行代碼行時調(diào)用了這個是調(diào)用返回的對象這個對象的方法如下圖方法首先它會調(diào)用這個方法這個方法很簡單就是比較這兩個值是不是相等不相等就拋出異常如下圖這兩個值為什么會不相
單線程的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); } } }
以上代碼會出現(xiàn)如下異常
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();
我們在執(zhí)行代碼22行時調(diào)用了it.next();這個it是ArrayList調(diào)用iterator()返回的對象;這個對象的next()方法如下圖:
public E next() { checkForComodification(); ...
next()方法首先它會調(diào)用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()方法,直接創(chuàng)建了一個私有的內(nèi)部類Itr的對象;expectedModCount 就是定義在這個Itr中的成員變量,而且,在初始化的時候,將modCount賦值給expectedModCount,說明在剛生成Iterator的時候這兩個值是相等的.modCount是定義在哪里呢,看下面源碼
public class ArrayListextends AbstractList ... protected transient int modCount = 0;
modCount是AbstractList的成員變量,ArrayList繼承下來了.所以modCount代表ArrayList的實(shí)際長度.
當(dāng)我們在iterator的迭代過程中改變了ArrayList的長度,就導(dǎo)致modCount變了,而expectedModCount 沒有變,導(dǎo)致不相等報錯
可是為什么用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方法不會拋出這個異常
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/76300.html
摘要:單線程的迭代過程中刪除集合元素以上代碼會出現(xiàn)如下異常從后往前看第行代碼我們在執(zhí)行代碼行時調(diào)用了這個是調(diào)用返回的對象這個對象的方法如下圖方法首先它會調(diào)用這個方法這個方法很簡單就是比較這兩個值是不是相等不相等就拋出異常如下圖這兩個值為什么會不相 單線程的Iterator迭代過程中刪除集合元素 public class TestIterator { public static voi...
摘要:單線程的迭代過程中刪除集合元素以上代碼會出現(xiàn)如下異常從后往前看第行代碼我們在執(zhí)行代碼行時調(diào)用了這個是調(diào)用返回的對象這個對象的方法如下圖方法首先它會調(diào)用這個方法這個方法很簡單就是比較這兩個值是不是相等不相等就拋出異常如下圖這兩個值為什么會不相 單線程的Iterator迭代過程中刪除集合元素 public class TestIterator { public static voi...
摘要:迭代器智能嗎第一步,將列表中的根節(jié)點(diǎn)找出來。源碼翻開中迭代器的源碼。在迭代器對象執(zhí)行操作之前,都會執(zhí)行方法,以判斷當(dāng)前操作下是否安全。 引言 ConcurrentModificationException這個異常大家都很熟悉,當(dāng)在forEach進(jìn)行刪除時都會出現(xiàn)該異常。 如果你還不了解,請參考澍澍的博客:關(guān)于在list循環(huán)的過程中進(jìn)行刪除的處理 - 晨澍的博客 showImg(http...
摘要:迭代器智能嗎第一步,將列表中的根節(jié)點(diǎn)找出來。源碼翻開中迭代器的源碼。在迭代器對象執(zhí)行操作之前,都會執(zhí)行方法,以判斷當(dāng)前操作下是否安全。 引言 ConcurrentModificationException這個異常大家都很熟悉,當(dāng)在forEach進(jìn)行刪除時都會出現(xiàn)該異常。 如果你還不了解,請參考澍澍的博客:關(guān)于在list循環(huán)的過程中進(jìn)行刪除的處理 - 晨澍的博客 showImg(http...
摘要:源碼分析構(gòu)造方法有兩個構(gòu)造方法,一個是無參,另一個需傳入初始容量值。所以我們可以把上面的代碼轉(zhuǎn)換一下,等價于下面形式這個時候,我們再去分析一下的迭代器源碼就能找出原因。原因是刪除元素后,元素計數(shù)器,而迭代器中的也等于,從而導(dǎo)致返回。 1.概述 ArrayList 是一種變長的集合類,基于定長數(shù)組實(shí)現(xiàn)。ArrayList 允許空值和重復(fù)元素,當(dāng)往 ArrayList 中添加的元素數(shù)量大于...
閱讀 2259·2023-04-26 01:50
閱讀 715·2021-09-22 15:20
閱讀 2595·2019-08-30 15:53
閱讀 1596·2019-08-30 12:49
閱讀 1714·2019-08-26 14:05
閱讀 2714·2019-08-26 11:42
閱讀 2309·2019-08-26 10:40
閱讀 2602·2019-08-26 10:38