遍历删除_面试难题:List 如何一边遍历,一边删除?
1. 新手常犯的錯誤
可能很多新手(包括當(dāng)年的我,哈哈)第一時間想到的寫法是下面這樣的:
public?static?void?main(String[]?args)?{????List?platformList?=?new?ArrayList<>();????platformList.add("博客園");????platformList.add("CSDN");????platformList.add("掘金");????for?(String?platform?:?platformList)?{????????if?(platform.equals("博客園"))?{????????????platformList.remove(platform);????????}????}????System.out.println(platformList);}然后滿懷信心的去運(yùn)行,結(jié)果竟然拋java.util.ConcurrentModificationException異常了,翻譯成中文就是:并發(fā)修改異常。
是不是很懵,心想這是為什么呢?
讓我們首先看下上面這段代碼生成的字節(jié)碼,如下所示:
由此可以看出,foreach循環(huán)在實(shí)際執(zhí)行時,其實(shí)使用的是Iterator,使用的核心方法是hasnext()和next()。
然后再來看下ArrayList類的Iterator是如何實(shí)現(xiàn)的呢?
可以看出,調(diào)用next()方法獲取下一個元素時,第一行代碼就是調(diào)用了checkForComodification();,而該方法的核心邏輯就是比較modCount和expectedModCount這2個變量的值。
在上面的例子中,剛開始modCount和expectedModCount的值都為3,所以第1次獲取元素"博客園"是沒問題的,但是當(dāng)執(zhí)行完下面這行代碼時:
platformList.remove(platform);modCount的值就被修改成了4。
所以在第2次獲取元素時,modCount和expectedModCount的值就不相等了,所以拋出了java.util.ConcurrentModificationException異常。
既然不能使用foreach來實(shí)現(xiàn),那么我們該如何實(shí)現(xiàn)呢?
主要有以下3種方法:
- 使用Iterator的remove()方法
- 使用for循環(huán)正序遍歷
- 使用for循環(huán)倒序遍歷
接下來一一講解。
2. 使用Iterator的remove()方法
使用Iterator的remove()方法的實(shí)現(xiàn)方式如下所示:
public?static?void?main(String[]?args)?{????List?platformList?=?new?ArrayList<>();????platformList.add("博客園");????platformList.add("CSDN");????platformList.add("掘金");????Iterator?iterator?=?platformList.iterator();????while?(iterator.hasNext())?{????????String?platform?=?iterator.next();????????if?(platform.equals("博客園"))?{????????????iterator.remove();????????}????}????System.out.println(platformList);}輸出結(jié)果為:
[CSDN,?掘金]為什么使用iterator.remove();就可以呢?
讓我們看下它的源碼:
可以看出,每次刪除一個元素,都會將modCount的值重新賦值給expectedModCount,這樣2個變量就相等了,不會觸發(fā)java.util.ConcurrentModificationException異常。更多面試題,歡迎關(guān)注公眾號 Java面試題精選
3. 使用for循環(huán)正序遍歷
使用for循環(huán)正序遍歷的實(shí)現(xiàn)方式如下所示:
public?static?void?main(String[]?args)?{????List?platformList?=?new?ArrayList<>();????platformList.add("博客園");????platformList.add("CSDN");????platformList.add("掘金");????for?(int?i?=?0;?i?這種實(shí)現(xiàn)方式比較好理解,就是通過數(shù)組的下標(biāo)來刪除,不過有個注意事項就是刪除元素后,要修正下下標(biāo)的值:
i?=?i?-?1;為什么要修正下標(biāo)的值呢?
因為剛開始元素的下標(biāo)是這樣的:
第1次循環(huán)將元素"博客園"刪除后,元素的下標(biāo)變成了下面這樣:
第2次循環(huán)時i的值為1,也就是取到了元素”掘金“,這樣就導(dǎo)致元素"CSDN"被跳過檢查了,所以刪除完元素后,我們要修正下下標(biāo),這也是上面代碼中i = i - 1;的用途。更多面試問題可以關(guān)注微信訂閱號碼匠筆記回復(fù)面試獲取
4. 使用for循環(huán)倒序遍歷
使用for循環(huán)倒序遍歷的實(shí)現(xiàn)方式如下所示:
public?static?void?main(String[]?args)?{????List?platformList?=?new?ArrayList<>();????platformList.add("博客園");????platformList.add("CSDN");????platformList.add("掘金");????for?(int?i?=?platformList.size()?-?1;?i?>=?0;?i--)?{????????String?item?=?platformList.get(i);????????if?(item.equals("掘金"))?{????????????platformList.remove(i);????????}????}????System.out.println(platformList);}這種實(shí)現(xiàn)方式和使用for循環(huán)正序遍歷類似,不過不用再修正下標(biāo),因為剛開始元素的下標(biāo)是這樣的:
第1次循環(huán)將元素"掘金"刪除后,元素的下標(biāo)變成了下面這樣:
第2次循環(huán)時i的值為1,也就是取到了元素”CSDN“,不會導(dǎo)致跳過元素,所以不需要修正下標(biāo)。
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎總結(jié)
以上是生活随笔為你收集整理的遍历删除_面试难题:List 如何一边遍历,一边删除?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: excel打开csv错误换行_「乱吐槽·
- 下一篇: SparkStreaming基础