javalist移除符合条件的元素_Java中List遍历删除元素
remove()的⽅法
今天碰见根据条件进⾏list遍历remove的问题,第⼀时间就是简单for循环remove,只知道这么写不⾏,不安全,可是为什么呢?你想过吗?下⾯就关于list遍历remove的问题,深挖⼀下!
⼀、⼏种常见的遍历⽅式
1、普通for循环
2、⾼级for循环
3、iterator和removeif
4、stream()
5、复制
6、普通for循环 --> 倒序⽅式
⼆、源码篇
1、普通for循环出错原因
public boolean remove(object o) {
if (o == null) {
for (int index = 0; index < size; index++) if (elementdata[index] == null) { fastremove(index);
return true;
}
} else {
for (int index = 0; index < size; index++) if (o.equals(elementdata[index])) { fastremove(index);
return true;
}
}
return false;
}
/*
* private remove method that skips bounds checking and does not
* return the value removed.
*/
private void fastremove(int index) {
modcount++;
int nummoved = size - index - 1;
if (nummoved > 0)
/
/remove会导致之后的元素往前移动,⽽下标不改变时就会出现bug
system.arraycopy(elementdata, index+1, elementdata, index,
nummoved);
elementdata[--size] = null; // clear to let gc do its work
}
我们在删除某个元素后,list的⼤⼩发⽣了变化,这时候你的的索引也会发⽣变化,这时就会导致你在遍历的时候漏掉某些元素。
⽐如当你删除第1个元素后,我们如果还是继续根据索引访问第2个元素时,因为删除的关系,后⾯的元素都往前移动了⼀位,所以实际访问的是第3个元素。
所以这种⽅式可以⽤在删除特定的⼀个元素时使⽤,但不适合循环删除多个元素时使⽤。
2、⾼级for循环出错原因
foreach其实是⽤迭代器来进⾏遍历的,⽽在遍历时直接使⽤arraylist的remove⽅法会导致什么问题呢?
可以再看⼀下fastremove和迭代器遍历的内部代码:
最后导致抛出上⾯异常的其实就是这个,简单说,调⽤ve()⽅法导致modcount和expectedmodcount的值不⼀致⽽报异常final void checkforcomodification() {
if (modcount != expectedmodcount)
throw new concurrentmodificationexception();
}java中index是什么意思
//调⽤next时会调⽤checkforcomodification⽅法检查 这两个字段
//⽽fastremove⾥⾯只对modcount 进⾏了改变 导致抛出异常
public e next() {
checkforcomodification();
int i = cursor;
if (i >= size)
throw new nosuchelementexception();
object[] elementdata = arraylist.this.elementdata;
if (i >= elementdata.length)
throw new concurrentmodificationexception();
cursor = i + 1;
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论