List如何选择迭代器进行remove


1.list 如何选择使用选择使用迭代进行移除元素

(1)、使用foreach进行迭代

public static void main(String[] args) {

  List<String> list = new ArrayList<>();
  list.add("123");
  list.add("345");
  list.add("456");

      for (String str:list) {
          if (str.startsWith("1")){
              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 com.datahunter.cn.TestModel.TestCoolection.main(TestCoolection.java:20)

为什么会造成该异常:源码分析

在ArraysList中的Itr内部类中 会使用迭代器去迭代而以上代码编译后的结果为:

Iterator var2 = list.iterator();

while(var2.hasNext()) {
  String str = (String)var2.next();
  if (str.startsWith("1")) {
      list.remove(str); // 调用list中remove方法
  }
}
 会执行next方法做验证。
 public E next() {
        checkForComodification(); //对modCount和expectedModCount验证
        int i = cursor;
        if (i >= SubList.this.size)
             throw new NoSuchElementException();
        Object[] elementData = ArrayList.this.elementData;
        if (offset + i >= elementData.length)
             throw new ConcurrentModificationException();
          cursor = i + 1;
          return (E) elementData[offset + (lastRet = i)];
      }

当使用 list.remove(str)方法时,并没有对于modCount和expectedModCount进行同步操作则会出现异常情况

(2)、使用for循环遍历元素时并不会出现异常,移除元素

for (int i=0;i<list.size();i++){

  if (list.get(i).startsWith("1")){

          list.remove(i);
      }
}
  System.out.println(list);
}

为什么不会出现异常

public E remove(int index) {
  rangeCheck(index);//对于数组长度的校验,并没有对操作次数做校验。

  modCount++;
  E oldValue = elementData(index);

  int numMoved = size - index - 1;
  if (numMoved > 0)
      System.arraycopy(elementData, index+1, elementData, index,
                        numMoved);
  elementData[--size] = null; // clear to let GC do its work

  return oldValue;
}

(3)、使用迭代器遍历元素,移除元素

迭代器会执行Itr内部类

Iterator<String> iterator = list.iterator();

while (iterator.hasNext()){
  if (iterator.next().startsWith("1")){
      iterator.remove();
  }
}
System.out.println(list);

执行Itr内部类中的remove方法();

public void remove() {
  if (lastRet < 0)
      throw new IllegalStateException();
  checkForComodification(); //验证modCount与expectedModCount

  try {
      ArrayList.this.remove(lastRet);
      cursor = lastRet;
      lastRet = -1;
      expectedModCount = modCount; //会将modCount和expectedModCount进行同步
      //modCount 指的是list每一次操作的统计数值
  } catch (IndexOutOfBoundsException ex) {
      throw new ConcurrentModificationException();
  }
}

 

List 中的remove源码

public E remove(int index) {
  rangeCheck(index);

  modCount++;
  E oldValue = elementData(index);

  int numMoved = size - index - 1;
  if (numMoved > 0)
      System.arraycopy(elementData, index+1, elementData, index,
                        numMoved);
  elementData[--size] = null; // clear to let GC do its work

  return oldValue;
   }

System.arraycopy()效果如下图

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM