为什么阿里巴巴代码规范不允许for循环里使用add/remove方法

为什么阿里巴巴代码规范不允许for循环里使用add/remove方法

主要是remove方法,add方法在for循环内使用不当可能会死循环

不要在foreach循环里进行元素的remove/add操作,remove元素请使用Iterator方式。
Negative example:   
   List<String> originList = new ArrayList<String>();
   originList.add("22");
   for (String item : originList) { 
      //warn
      list.add("bb");
   }  
        
       
       
 Positive example: 
   Iterator<Integer> it=b.iterator();		 
   while(it.hasNext()){                      
      Integer temp =  it.next();             
      if (delCondition) {
          it.remove();
      }
   } 

List的remove方法&Iterator的remove方法

// ArrayList.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;
}
// ArrayList.iterator().remove
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();
    }
}

List的remove问题:
从源码中可以看出,举例size为10,index=4时在循环内调用了List的remove方法;
将会把下标5~9的元素copy到下标4~8,并将下标9置为null;
但是当前for循环已经处理了下标4,下次直接处理下标5,这样就导致新copy到下标4的属性被漏掉;
Iterator的处理:
从源码中可以看出Iterator中也是调用的同一个remove方法,但是将cursor重新赋值为刚处理的下标;
以上面的例子当调用next方法获取到index=4的元素时cursor=5,如果调用Integer的remove方法,内部调用完List的remove方法后,cursor被置为4;
这样再次调用next方法时就还获取index=4的元素,就不会遗漏数据了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值