任何时候都不要在 for 轮回中删除 List 聚集元素
媒介
起首说结论:无论什么场景,都不要对List利用for轮回的同时,删除List聚集元素,因为那么做就是不合错误的。
阿里开发手册也明白阐明制止利用foreach删除、增加List元素。
准确删除元素的体例是利用迭代器(Iterator),代码如下:
ListString list = new ArrayList();
IteratorString iterator = list.iterator();
while (iterator.hasNext()) {
// 删除元素
iterator.remove();
JDK8后lambda写法:list.removeIf(s - s.contains("a"));
不想晓得为什么不克不及利用for轮回删除List聚集元素的,看完媒介就能够封闭本页面了,想晓得原因的陆续往下看
实例
下面举个实例场景,看一下为什么不克不及利用for轮回。
需求
一个List聚集,元素类型为String,有N个元素,删除那些元素中包罗字符''a''的元素。
假设聚集内容如下:
ListString list = new ArrayList(4);
list.add("a");
list.add("ab");
list.add("abc");
list.add("abcd");
准确谜底
展开全文
先上准确谜底
public static void main(String[] args) {
ListString list = new ArrayList(4);
list.add("a");
list.add("ab");
list.add("abc");
list.add("abcd");
IteratorString iterator = list.iterator();
while (iterator.hasNext()) {
if (iterator.next().contains("a")) {
// 删除元素
iterator.remove();
System.out.println(list);
输出成果为
错误谜底1:通俗for轮回(for-i)
public static void main(String[] args) {
ListString 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轮回遍历List聚集的同时,删除List中的元素是能够运行的代码,但在大大都场景下,不克不及利用那种体例,上边的成果也印证了那一点,固然你的代码不会报错,运行也一般,但在本实例中,那么写就是BUG。
BUG原因:索引为i的元素删除后,后边元素的索引主动向前补位,即本来索引为i+1的元素,变成了索引为i的元素,但是下一次轮回取的索引是i+1,此时你认为取到的是本来索引为i+1的元素,其实取到是本来索引为i+2的元素。
只要每删除一个元素,就会漏掉下一个元素,所以那种体例从逻辑上来说是存在bug的,无论什么需求场景,都不料见用那种体例,因为不成控因素太多(鬼晓得消费情况中他会删掉几元素,同时漏掉几元素)。
既然那么写不报错,那么个别特殊场景确实能够利用那种通俗for轮回删除元素的,好比我们把实例的需求变更一下,改为:一个List聚集,元素类型为String,有N个元素,删除那些元素中包罗字符'a'的元素,假设有持续两个或以上元素包罗'a',那么只删除当前持续元素中的奇数位元素。固然那种场景适用,但仍然不选举,仍是因为太不成控。
错误谜底2:加强for轮回(foreach)
public static void main(String[] args) {
ListString 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:并发修改反常
阐发
其实那里没啥好阐发的,间接报错了,你还那么写干嘛?没事找功受吗。。。
能够简单的理解为:foreach就不撑持对聚集中的元素停止增删操做,但是能够修改。