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