foreach判断最后一个_ArrayList集合为什么不能使用foreach增删改?
點擊上方“Java技術前線”,選擇“置頂或者星標”
與你一起成長
譯者:奮斗的小程序員鏈接:http://suo.im/4XaI8Q
編程過程中常常需要使用到集合,而ArrayList也是我們常常使用的,但是最近在一次刪除和增加中出現了一些問題,分享記錄下。
請看下面兩段代碼,哪段代碼會報錯呢,或者都成功呢。
List?arrayList1?=?new?ArrayList();arrayList1.add("1");
arrayList1.add("2");for?(String?s?:?arrayList1)?{if("1".equals(s)){
?arrayList1.remove(s);
?}
}
List?arrayList2?=?new?ArrayList();
arrayList2.add("2");
arrayList2.add("1");for?(String?s?:?arrayList2)?{if("1".equals(s)){
?arrayList2.remove(s);
?}
}
程序運行結果如下:
arrayList1的remove方法成功執行,但是arrayList2的remove方法運行拋出ConcurrentModificationException異常。
為了尋找原因,我們只能看源代碼了。
因為foreach的本質就是使用的迭代器Iterator,所有的Collection集合類都會實現Iterable接口。
找到ArrayList類的iterator()方法
使用自己的Itr內部類,并且實現了Iterator接口
迭代器的本質是先調用hasNext()方法判斷存不存在下一個元素,然后再使用next()方法取下一個元素
Itr內部類實現
上面arraylist1為什么能remove成功呢,其實它只循環了一次,所以成功了。
因為它在remove元素1之后,它的size - 1變成1,然后Itr內部的cursor變量由0變成1
此時1 = 1,循環結束,所以成功了。
arraylist2為什么remove失敗呢,因為他在循環第二次的時候,也remove成功了,但是第三次判斷next的時候cursor的值為2導致不等于現在的size 1,所以執行了next方法,最重要的來了,之前remove的操作導致ArrayList的modCount值加1,然后Itr類中的expectedModCount保持不變,所以會拋出異常。
同理可得,由于add操作也會導致modCount自增,所以不允許在foreach中刪除、增加、修改ArrayList中的元素。
對此,推薦大家使用迭代器Iterator刪除元素,
Iterator?iterator?=?arrayList2.iterator();while(iterator.hasNext()){?String?item?=?iterator.next();if("1".equals(item)){
?iterator.remove();
?}
}
如果存在并發操作,還需要對Iterator進行加鎖操作。
-?end?-
用心分享面試知識,做有溫度的攻城獅
每天記得對自己說:你是最棒的!
往期推薦:為啥國人偏愛 Mybatis,而老外喜歡 Hibernate/JPA 呢?
- 做一個完整的Java Web項目需要掌握的技能
- GC 性能優化4 – GC 算法(基礎篇)
- SpringBoot 快速整合Mybatis(去XML化+注解進階)
- 我眼中的技術地圖
- 誰說用 Git 一定要用命令行?試試 SourceTree 吧
- Java爬取并下載酷狗TOP500歌曲
- MySQL update語句一個“經典”的坑
- Google 出品的 Java 編碼規范,強烈推薦,權威又科學!
- Spring Boot 注解大全,真是太全了!
- 前后端分離必備的接口規范,十分接地氣!
- 漲姿勢了,寫代碼注意了,打死都不要用 User 這個單詞
? ? ? ? ? ? ? ? ? ? ?每一個“好看”,都是對我們最大的肯定!
總結
以上是生活随笔為你收集整理的foreach判断最后一个_ArrayList集合为什么不能使用foreach增删改?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 出发a标签_以用户标签为例,复盘B端产品
- 下一篇: c语言getch() 头文件,用getc