List中remove()方法的陷阱,被坑惨了!
Java之间
共 1054字,需浏览 3分钟
·
2021-10-10 11:32
1、7 种 Spring Boot 注入 Bean 的方式 2、再见MybatisPlus,阿里推出新ORM框架! 3、为什么不推荐使用BeanUtils属性转换工具 4、SpringBoot巧用 @Async 提升API接口并发能力 5、一个Bug能有多大影响:亏损30亿、致6人死亡、甚至差点毁灭世界...
list.remove(o)
/remove(i)
方法。在使用时,容易触碰陷阱,得到意想不到的结果。总结以往经验,记录下来与大家分享。package com.cicc.am.test;
import java.util.ArrayList;
import java.util.List;
public class ListTest {
public static void main(String[] args) {
Listlist=new ArrayList ();
list.add(1);
list.add(2);
list.add(3);
list.add(3);
list.add(4);
System.out.println(list);
}
}
错误
!!!for(int i=0;i if(list.get(i)==3) list.remove(i);
}
System.out.println(list);
正确
!for(int i=0;i if(list.get(i)==3) list.remove(i--);
}
System.out.println(list);
正确
!for(int i=list.size()-1;i>=0;i--){
if(list.get(i)==3){
list.remove(i);
}
}
System.out.println(list);
错误
!!!for(Integer i:list){
if(i==3) list.remove(i);
}
System.out.println(list);
java.util.ConcurrentModificationException
List.iterator()
源码着手分析,跟踪iterator()
方法,该方法返回了 Itr 迭代器对象。public Iterator iterator() {
return new Itr();
}
private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")
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;
return (E) elementData[lastRet = i];
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
modCount != expectedModCount
是否相等,如果不相等则抛出ConcurrentModificationException
异常。expectedModCount = modCount
赋值,保证两个值相等,那么问题基本上已经清晰了,在 foreach 循环中执行 list.remove(item);
,对 list 对象的 modCount 值进行了修改,而 list 对象的迭代器的 expectedModCount 值未进行修改,因此抛出了ConcurrentModificationException
异常。正确
!Iterator it=list.iterator();
while(it.hasNext()){
if(it.next()==3){
it.remove();
}
}
System.out.println(list);
Iterator.remove()
方法会在删除当前迭代对象的同时,会保留原来元素的索引。所以用迭代删除元素是最保险的方法,建议大家使用List过程错误
!!!Iterator it=list.iterator();
while(it.hasNext()){
Integer value=it.next();
if(value==3){
list.remove(value);
}
}
System.out.println(list);
java.util.ConcurrentModificationException
,原理同上述方法4.list.remove(2);
System.out.println(list);
remove(object)
方法,需要传入Integer类型,代码如下:list.remove(new Integer(2));
System.out.println(list);
最近热文阅读:
1、7 种 Spring Boot 注入 Bean 的方式 2、再见MybatisPlus,阿里推出新ORM框架! 3、为什么不推荐使用BeanUtils属性转换工具 4、SpringBoot巧用 @Async 提升API接口并发能力 5、一个Bug能有多大影响:亏损30亿、致6人死亡、甚至差点毁灭世界... 6、Java17,有史以来最快 JDK! 7、Spring Boot + MyBatis + MySQL读写分离 8、从MySQL 5.6升级到8.0,Facebook付出了惨痛代价…… 9、吊打 ThreadLocal,谈谈FastThreadLocal为啥能这么快? 10、手写了一个简单的JSON解析器,网友直乎:牛! 关注公众号,你想要的Java都在这里
评论