首先說結論:無論什么場景,都不要對List使用for循環(huán)的同時,刪除List集合元素,因為這么做就是不對的。
阿里開發(fā)手冊也明確說明禁止使用foreach刪除、增加List元素。
正確刪除元素的方式是使用迭代器(Iterator),代碼如下:
List<String> list = new ArrayList<>();
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
// 刪除元素
iterator.remove();
}
JDK8后lambda寫法:
list.removeIf(s -> s.contains("a"));
不想知道為什么不能使用for循環(huán)刪除List集合元素的,看完前言就可以關閉本頁面了,想知道原因的繼續(xù)往下看
下面舉個實例場景,看一下為什么不能使用for循環(huán)。
需求
一個List集合,元素類型為String,有N個元素,刪除這些元素中包含字符’‘a(chǎn)’'的元素。
假設集合內容如下:
List<String> list = new ArrayList<>(4);
list.add("a");
list.add("ab");
list.add("abc");
list.add("abcd");
public static void main(String[] args) {
List<String> list = new ArrayList<>(4);
list.add("a");
list.add("ab");
list.add("abc");
list.add("abcd");
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
if (iterator.next().contains("a")) {
// 刪除元素
iterator.remove();
}
}
System.out.println(list);
}
輸出結果為
[]
錯誤答案1:普通for循環(huán)(for-i)
public static void main(String[] args) {
List<String> list = new ArrayList<>(4);
list.add("a");
list.add("ab");
list.add("abc");
list.add("abcd");
for (int i = 0; i < list.size(); i++) {
if (list.get(i).contains("a")) {
list.remove(i);
}
}
System.out.println(list);
}
輸出結果為
[ab, abcd]
分析
普通for循環(huán)遍歷List集合的同時,刪除List中的元素是可以運行的代碼,但在大多數(shù)場景下,不能使用這種方式,上邊的結果也印證了這一點,雖然你的代碼不會報錯,運行也正常,但在本實例中,這么寫就是BUG。
BUG原因:索引為i的元素刪除后,后邊元素的索引自動向前補位,即原來索引為i+1的元素,變?yōu)榱怂饕秊閕的元素,但是下一次循環(huán)取的索引是i+1,此時你以為取到的是原來索引為i+1的元素,其實取到是原來索引為i+2的元素。
只要每刪除一個元素,就會漏掉下一個元素,所以這種方式從邏輯上來說是存在bug的,無論什么需求場景,都不建議用這種方式,因為不可控因素太多(鬼知道生產(chǎn)環(huán)境中他會刪掉多少元素,同時漏掉多少元素)。
既然這么寫不報錯,那么個別特殊場景確實可以使用這種普通for循環(huán)刪除元素的,比如我們把實例的需求變動一下,改為:一個List集合,元素類型為String,有N個元素,刪除這些元素中包含字符’a’的元素,如果有連續(xù)兩個或以上元素包含’a’,那么只刪除當前連續(xù)元素中的奇數(shù)位元素。雖然這種場景適用,但仍然不推薦,還是因為太不可控。
錯誤答案2:增強for循環(huán)(foreach)
public static void main(String[] args) {
List<String> list = new ArrayList<>(4);
list.add("a");
list.add("ab");
list.add("abc");
list.add("abcd");
for (String str : list) {
if (str.contains("a")) {
list.remove(str);
}
}
System.out.println(list);
}
運行報錯:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
at java.util.ArrayList$Itr.next(ArrayList.java:859)
at top.oldmoon.learn.test.ListTest.main(ListTest.java:24)
使用百度翻譯可以知道:Concurrent Modification Exception:并發(fā)修改異常
分析文章來源:http://www.zghlxwxcb.cn/news/detail-413810.html
可以簡單的理解為:foreach就不支持對集合中的元素進行增刪操作,但是可以修改。文章來源地址http://www.zghlxwxcb.cn/news/detail-413810.html
到了這里,關于任何時候都不要在 for 循環(huán)中刪除 List 集合元素?。。〉奈恼戮徒榻B完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!