在foreach循环集合时需要注意的问题

这里以ArrayList为例

源代码

public class ArrayListDemo {
    public  static void main(String[] args) {

        //list
        List<Integer> list = new ArrayList<Integer>();
        list.add(234);
        list.add(121);

        for(Integer dat:list){
            System.out.println(dat);
        }
    }
}

使用javap -c 查看编译后的class文件

javap -c ArrayListDemo

输出

public static void main(java.lang.String[]);
    Code:
       0: new           #2                  // class java/util/ArrayList
       3: dup
       4: invokespecial #3                  // Method java/util/ArrayList."<init>":()V
       7: astore_1
       8: aload_1
       9: sipush        234
      12: invokestatic  #4                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      15: invokeinterface #5,  2            // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
      20: pop
      21: aload_1
      22: bipush        121
      24: invokestatic  #4                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      27: invokeinterface #5,  2            // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
      32: pop
      33: aload_1
      //调用的是iterator
      34: invokeinterface #6,  1            // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
      39: astore_2
      40: aload_2
       //调用的是iterator
      41: invokeinterface #7,  1            // InterfaceMethod java/util/Iterator.hasNext:()Z
      46: ifeq          69
      49: aload_2
       //调用的是iterator
      50: invokeinterface #8,  1            // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      55: checkcast     #9                  // class java/lang/Integer
      58: astore_3
      59: getstatic     #10                 // Field java/lang/System.out:Ljava/io/PrintStream;
      62: aload_3
      63: invokevirtual #11                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      66: goto          40
      69: return

可以看到,foreach 循环内部实际是通过 Iterator 实现的.
上面的代码等同于


Iterator it = list.iterator();
while(it.hasNext())
{
   System.out.println(it.next());
}

Iterator实现类Itr是ArrayList的一个内部类.modCount是ArrayList类t的一个私有属性,当对ArrayList进行添加或者删除元素时就会修改该值.ArrayList使用其来判断是否存在元素数量的变化.
在迭代过程中通过checkForComodification不断检测元素数量是否存在变化,如果有变化会抛出ConcurrentModificationException异常.

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
   //创建内部类保存当前的modCount
   int expectedModCount = modCount;

   // prevent creating a synthetic constructor
   Itr() {}

   public boolean hasNext() {
       return cursor != size;
   }

   @SuppressWarnings("unchecked")
   public E next() {
   //在迭代过程中比较expectedModCount 和 modCount是否不一致
       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() {
    if (modCount != expectedModCount)
         throw new ConcurrentModificationException();
 }
}

综上所述,当在foreach循环中修改集合会出现的问题ConcurrentModificationException异常.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值