码迷,mamicode.com
首页 > 其他好文 > 详细

【搬砖系列】如何在遍历List时安全删除集合元素

时间:2018-11-02 01:45:53      阅读:683      评论:0      收藏:0      [点我收藏+]

标签:his   test   hide   删掉   except   简单   ica   初始   完成   

 

技术分享图片
 1 public void testIterRemove() {
 2         List l1 = new ArrayList(Arrays.asList(1, 2, 3, 4, 5));
 3         Iterator<Integer> iterator = l1.iterator();
 4         System.out.println("before=" + l1);
 5         while (iterator.hasNext()) {
 6             iterator.next();
 7             iterator.remove();
 8         }
 9         System.out.println("after=" + l1);
10 }
11 /*
12 before=[1, 2, 3, 4, 5]
13 after=[]
14 */
遍历时移除元素的正确示例

代码中关键的部分在于:

iterator.next();

iterator.remove();

二者缺一不可。当然调用next()之前要调用hasNext()确保没有越界。

简单分析两个方法的代码即可得出答案:

首先看remove()方法,为什么hasNext() + remove()不可以呢:

技术分享图片
 1         public void remove() {
 2             if (lastRet < 0)
 3                 throw new IllegalStateException();
 4             checkForComodification();
 5 
 6             try {
 7                 ArrayList.this.remove(lastRet);
 8                 cursor = lastRet;
 9                 lastRet = -1;
10                 expectedModCount = modCount;
11             } catch (IndexOutOfBoundsException ex) {
12                 throw new ConcurrentModificationException();
13             }
14         }
ArrayList#Itr.remove()

由于代码用属性lastRet(即lastReturn index)控制异常,所以查看ArrayList#Itr的实例初始化语句,lastRet初值是-1,如果单独调用remove()会报错。

再看一下next()方法,就会找出答案:

技术分享图片
 1         public E next() {
 2             checkForComodification();
 3             int i = cursor;
 4             if (i >= size)
 5                 throw new NoSuchElementException();
 6             Object[] elementData = ArrayList.this.elementData;
 7             if (i >= elementData.length)
 8                 throw new ConcurrentModificationException();
 9             cursor = i + 1;
10             return (E) elementData[lastRet = i];
11         }
ArrayList#Itr.next()

在方法中首先将cursor记录到变量 i,返回前将 i 的知赋给 lastRet ,完成lastRet的更新。方法返回值不是本次要考虑的范畴。

再回过头看remove()方法,有了lastRet后,就可以重置cursor。在方法中调用了ArrayList#remove(),这个方法会重新调整数组元素的位置,如果删掉的不是最后一个位置的元素(numMoved == 0 表示删掉的正好是最后一位元素),将会把index后面的元素往前移动一个,最后将elementData[--size] = null 为移除旧元素,帮助GC。

 

总结:

需要先调用next()更新lastRet的值,才能在remove()中通过第一关对lastRet的检查。因此在遍历List时需要联合使用 :

while( it.hasNext() ) 
{ 
    it.next(); 
    it.remove();
} 

 

【搬砖系列】如何在遍历List时安全删除集合元素

标签:his   test   hide   删掉   except   简单   ica   初始   完成   

原文地址:https://www.cnblogs.com/christmad/p/9893272.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!