谈谈自己的理解,错了请告诉我
回顾了一下ArrayList和LinkedList的数据结构,然后也被问到了循环中删除数会出现什么问题,因为只知道普通的for循环中删除数据会出问题,但具体会怎么样并不清楚,所以还是决定来理一理。
首先先说明自己理解的一点:虽然LinkedList底层是使用链表,但是它提供了类似ArrayList的下标形式数据访问,所以以下在以下标形式访问数据是看作和ArrayList一样。
迭代器形式循环
这个形式的循环只要使用迭代器的remove方法就能够正常地进行删除操作。如果使用集合的remove方法时会抛出ConcurrentModificationException异常
使用高级for循环
高级for循环底层实现是迭代器,所以也会抛出ConcurrentModificationException异常。但实际情况是有时候不会抛出异常,这个应该和底层实现有关(这个作为日后谈以后再更新在这里)
使用普通for循环
这个其实就比较有意思了,会出现部分数据被跳过的情况。
看一段简单代码说明一下出现这种情况的原因
List<String> list = new ArrayList<>();
list.add("str A");
list.add("str B");
list.add("str B");
list.add("str A");
list.add("str A");
for (int i = 0; i < list.size(); i++) {
if (list.get(i).indexOf('A') > 0)
list.remove(i);
}
//运行最后打印结果剩余
str B
str B
str A
一开始这个list里初始化了5个数据,经过了一次删除发现了部分数据剩余。原因是下标是从0开始的,那么在循环中删除0位置的数据的时候,0之后的数据的下标会-1,而for循环中i会自动加一,则会出现数据被跳过的情况。
如果改成
//一
for (int i = 0; i < list.size();) {
if (list.get(i).indexOf('A') > 0)
list.remove(i);
else
i++;
}
//二
for (int i = 0; i < list.size();i++) {
if (list.get(i).indexOf('A') > 0){
list.remove(i);
i--
}
}
这两种就会发现A已经被全部删除了,因为我们针对下标的变动做了手动处理。
其实看到这种的时候有想到倒序遍历会不会不需要手动对下标做处理,因为从末尾删除不会改变其他数据的下标,后来又想了想还是不行,果然还是要根据判断结果来处理下标。
其实前面的这种错误写法还行,只会造成漏删数据,但是下面的这种写法就很沙雕了,会直接数组越界。
int count = list.size()
for (int i = 0; i < count; i++) {
if (list.get(i).indexOf('A') > 0)
list.remove(i);
}
多此一举坑上坑。