ArrayList remove注意事项

Posted zhangxingsheng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ArrayList remove注意事项相关的知识,希望对你有一定的参考价值。

 

例子1:

List<Integer>list=new ArrayList<>();
 list.add(1);
 list.add(2);
 list.add(2);
 list.add(3);
 list.add(4);
 list.add(5);
 for(int i=0;i<list.size();i++){
  if(list.get(i)%2==0){
   list.remove(list.get(i));
  }
}
System.out.println(list);

 

输出结果:

[1, 2, 3, 5]

分析:
第三个元素没有remove 掉,跟踪:
第一次循环
i=0 size=5 当前元素=1 不移除元素
i=1 size=5 当前元素=2 移除元素
i=2 size=4 当前元素=3 不移除元素


在remove 的过程中 size 是移动的,所以 第三个元素给漏掉了

 

例子2:

List<Integer>list=new ArrayList<>();
list.add(1);
list.add(2);
list.add(2);
list.add(3);
list.add(4);
list.add(5);

System.out.println(list);*/

for (Integer a:list){
 if(a == 2){
  list.remove(a);
 }
}

  

抛出异常:

java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
at java.util.ArrayList$Itr.next(ArrayList.java:851)
at com.student.eureka1.StudentEureka1ApplicationTests.contextLoads(StudentEureka1ApplicationTests.java:31)

  

原因:
抛出异常代码

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];
}

final void checkForComodification() {
// 是因为 modCount != expectedModCount 不相等
  if (modCount != expectedModCount)
  throw new ConcurrentModificationException();
}

  

在使用for(Object obj:objList) 这种增强for 循环的时候,每次遍历会进行hasNext 判断,它会创建 List的遍历器Iterator ,在创建的时候它会将 modCount 赋值给 expectedModCount 。并且调用Iterator 的 next 方法,在没有调用 list.remove(a); 方法前,expectedModCount 和 modCount是相等的。当调用后注意 list.remove(a); 调用的不是Iterator 的remove 方法,而是 ArrayList的remove 方法, ArrayList的remove 方法 只会更新 modCount 值,不会更新expectedModCount 值,所以不相等报错(简单点就是说:你用了Iterator 遍历 但是在里面不是用Iterator  的 remove 方法导致)

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];
}

以上是关于ArrayList remove注意事项的主要内容,如果未能解决你的问题,请参考以下文章

在ArrayList上操作时,AbstractList.remove()中的UnsupportedOperationException

从面试角度聊聊 ArrayList 中的 remove 方法

ArrayList <Integer> 与 get/remove 方法

一个ArrayList在循环过程中删除,会不会出问题,为什么?

Java ArrayList在foreach中remove的问题分析

ArrayList.add 有效,但 ArrayList.remove 无效