日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

foreach迭代ArrayList时,真的不能删除元素吗?

發(fā)布時間:2025/3/21 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 foreach迭代ArrayList时,真的不能删除元素吗? 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

ArrayList是java開發(fā)時非常常用的類,常碰到需要對ArrayList循環(huán)刪除元素的情況。這時候大家都不會使用foreach循環(huán)的方式來遍歷List,因為它會拋java.util.ConcurrentModificationException異常。比如下面的代碼就會拋這個異常:

List<String>?list?=?new?ArrayList<>(); list.add("1"); list.add("2"); list.add("3"); list.add("4"); list.add("5");for?(String?item:?list)?{if?(item.equals("3"))?{list.remove(item);} } System.out.println(Arrays.toString(list.toArray()));

那是不是在foreach循環(huán)時刪除元素一定會拋這個異常呢?答案是否定的。

見這個代碼:

List<String>?list?=?new?ArrayList<>(); list.add("1"); list.add("2"); list.add("3"); list.add("4"); list.add("5");for?(String?item:?list)?{if?(string.equals("4"))?{list.remove(item);} } System.out.println(Arrays.toString(list.toArray()));

這段代碼和上面的代碼只是把要刪除的元素的索引換成了4,這個代碼就不會拋異常。為什么呢?

接下來先就這個代碼做幾個實驗,把要刪除的元素的索引號依次從1到5都試一遍,發(fā)現(xiàn),除了刪除4之外,刪除其他元素都會拋異常。接著把list的元素個數(shù)增加到7試試,這時候可以發(fā)現(xiàn)規(guī)律是,只有刪除倒數(shù)第二個元素的時候不會拋出異常,刪除其他元素都會拋出異常。

好吧,規(guī)律知道了,可以從代碼的角度來揭開謎底了。

首先java的foreach循環(huán)其實就是根據(jù)list對象創(chuàng)建一個Iterator迭代對象,用這個迭代對象來遍歷list,相當(dāng)于list對象中元素的遍歷托管給了Iterator,你如果要對list進行增刪操作,都必須經(jīng)過Iterator,否則Iterator遍歷時會亂,所以直接對list進行刪除時,Iterator會拋出ConcurrentModificationException異常

其實,每次foreach迭代的時候都有兩步操作():

  • iterator.hasNext() ?//判斷是否有下個元素

  • item = iterator.next() ?//下個元素是什么,并賦值給上面例子中的item變量

  • next()方法的代碼如下:

    @SuppressWarnings("unchecked") public?E?next()?{checkForComodification();int?i?=?cursor;if?(i?>=?size)throw?new?NoSuchElementException();Object[]?elementData?=?ArrayList.this.elementData;if?(i?>=?elementData.length)throw?new?ConcurrentModificationException();cursor?=?i?+?1;return?(E)?elementData[lastRet?=?i]; }final?void?checkForComodification()?{if?(modCount?!=?expectedModCount)throw?new?ConcurrentModificationException(); }

    這時候你會發(fā)現(xiàn)這個異常是在next方法的checkForComodification中拋出的,拋出原因是modCount != expectedModCount

    • modCount是指這個list對象從new出來到現(xiàn)在被修改次數(shù),當(dāng)調(diào)用List的add或者remove方法的時候,這個modCount都會增加;

    • expectedModCount是Iterator類中特有的變量,指現(xiàn)在期望這個list被修改的次數(shù)是多少次,這個值在調(diào)用list.iterator()創(chuàng)建iterator的時候初始化為modCount,該值在iterator初始化直到使用結(jié)束期間不會改變。

    iterator創(chuàng)建的時候modCount被賦值給了expectedModCount,但是調(diào)用list的add和remove方法的時候不會同時修改expectedModCount,這樣就導(dǎo)致下次取值時檢查到兩個count不相等,從而拋出異常。

    解決這個問題的一種方式是使用Iterator來操作列表:

    Iterator<String>?it?=?list.iterator(); while(it.hasNext())?{if?(it.next().equals("3"))?{it.remove();} }

    那么為什么這種方式不會拋出該異常呢?下面是ArrayList中內(nèi)部類Itr的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();} }

    注意下面這句:

    expectedModCount?=?modCount;

    可以看出,在使用iterator()方法得到的Iterator對象后,通過iterator.remove方法是可以正確刪除列表元素的,因為它保證了expectedModCount=modCount。

    避免這個問題的另一種方法,是不使用foreach語句的for循環(huán):

    for?(int?i?=?0;?i?<?list.size();?)?{String?s?=?list.get(i);if?(s.equals("3"))?{list.remove(i);continue;}i++; }

    回到問題上來,在使用foreach迭代ArrayList時,是可以刪除任何一個元素的,且只能刪除一個,而且這只能發(fā)生在迭代到倒數(shù)第二個元素的時候。比如下面的代碼不會有異常:

    List<String>?list?=?new?ArrayList<>(); list.add("1"); list.add("2"); list.add("3"); list.add("4"); list.add("5");for?(String?item:?list)?{if?(string.equals("4"))?{list.remove("5");?//刪除的不一定是當(dāng)前元素} } System.out.println(Arrays.toString(list.toArray()));

    其真正的原因是remove("5")這一句之后,下一次foreach語句將調(diào)用iterator.hasNext()方法,如果此時返回false,這樣就不會進到next()方法里了,也就不會調(diào)用checkForComodification而導(dǎo)致異常了。

    疑問:當(dāng)循環(huán)到倒數(shù)第二個元素時,如果再多刪除一個會怎樣呢?比如:

    for?(String?item:?list)?{if?(item.equals("4"))?{list.remove("1");list.remove("5");}System.out.println(Arrays.toString(list.toArray())); }

    這段代碼中,list是可以被打印出來的,因為list.remove()方法可以正確執(zhí)行,其結(jié)果也是正確的。但是執(zhí)行完這次打印,進入下一次迭代時,又產(chǎn)生了checkForComodification異常,還沒想明白為什么。如果哪位大牛知道,請留言。

    參考:

    http://rongmayisheng.com/post/%E7%A0%B4%E9%99%A4%E8%BF%B7%E4%BF%A1java-util-arraylist%E5%9C%A8foreach%E5%BE%AA%E7%8E%AF%E9%81%8D%E5%8E%86%E6%97%B6%E5%8F%AF%E4%BB%A5%E5%88%A0%E9%99%A4%E5%85%83%E7%B4%A0

    http://stackoverflow.com/questions/11042552/what-does-the-modcount-variable-when-debugging-the-collection


    from:?https://my.oschina.net/itblog/blog/422649

    總結(jié)

    以上是生活随笔為你收集整理的foreach迭代ArrayList时,真的不能删除元素吗?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 麻豆视频在线 | 在线观看自拍 | 国产乱子一区二区 | 男女激情实录 | h片免费网站| 五月天婷婷影院 | 奶妈的诱惑 | 91精品视频免费在线观看 | 伊人久久精品一区二区三区 | 午夜性生活片 | 日本激情电影 | 男受被做哭激烈娇喘gv视频 | 久草www | 中文字幕日韩欧美一区二区三区 | 大j8黑人w巨大888a片 | 黄色av免费在线观看 | 一二三区在线视频 | 国产伦理久久精品久久久久 | 国产免费黄色录像 | 亚洲九九精品 | 国产又色又爽无遮挡免费动态图 | 91蝌蚪视频在线观看 | 特级淫片裸体免费看冫 | 秘密爱大尺度做爰呻吟 | 成人激情社区 | 日韩视频免费观看高清完整版 | av网站免费在线观看 | 日韩中文免费 | 91一区二区三区在线观看 | 国产农村妇女精品一区二区 | 国产毛片毛片毛片毛片毛片 | 欧洲美一区二区三区亚洲 | 一起草av在线 | a天堂在线观看 | 国产精品视频一二三 | 亚洲人女屁股眼交6 | 大伊人网 | 日韩伊人网 | 日韩免费av | 成人性生交7777 | 91免费国产在线 | 国产精品久久久久久久久久久免费看 | 97精品人人a片免费看 | 97公开视频 | 成人高清视频在线观看 | 999资源站| 在线免费视频一区二区 | 亚洲午夜无码久久久久 | 两个女人互添下身爱爱 | 对白刺激国产子与伦 | 91理论片午午伦夜理片久久 | 国产超碰人人 | 久久久精品一区二区三区 | 自拍偷拍亚洲欧美 | 日本黄色录象 | 超黄av| 精品国产a线一区二区三区东京热 | 中文字幕人妻丝袜乱一区三区 | 国产成人综合在线观看 | 91成人精品国产刺激国语对白 | 亚洲激情成人网 | 一级黄色a | 国产精品成av人在线视午夜片 | 免费一级a毛片 | 欧美日韩国产激情 | 亚洲午夜国产 | av瑟瑟| 爱的色放韩国电影 | 中文字幕一区二区三区日韩精品 | 97国产在线播放 | 久久中文字幕在线 | 色噜噜综合 | 狠狠干天天操 | 小泽玛利亚一区二区三区 | 国产精品一区二区三区四区 | 欧产日产国产精品 | 蜜桃av噜噜一区二区三区麻豆 | 中国色老太hd | 国产又粗又长又硬免费视频 | 日本韩国欧美一区 | 无码人妻精品一区二区蜜桃网站 | 亚洲综合在 | 天天草夜夜草 | 在线免费观看日韩av | 国产精品久久久久久久久免费桃花 | youjizzxxx69 | 在线天堂av| 色婷婷久久五月综合成人 | 国产精欧美一区二区三区蓝颜男同 | 亚洲国产精品毛片av不卡在线 | 久久综合激的五月天 | 中文字幕第一区综合 | 日韩中文三级 | 视频在线观看免费 | 日韩高清中文字幕 | 久久久中文网 | 日韩极品一区 | 精品无码久久久久久国产 | xxxx国产视频 |