Java中Iterator(迭代器)与foreach学习

1.迭代器使用

Iterator(迭代器)给我们提供了一种遍历序列的方式,其中主要关于以下几种方法:

1.iterator()方法,返回一个Iterator对象。

2.next()方法,获取迭代器的下一个元素,并会向后移动一个单位(注:初次调用next()会返回序列中的第一个元素)

3.hasNext()方法,判断迭代器是否还有下一个元素(不会移动迭代器)

4.remover()方法,删除当前的迭代器所指向元素,一般与next()方法连用

 

Iterator遍历序列实施操作示例:

Iterator iter  = subjects.iterator();//subjects为字符串序列
while(iter.hasNext()){
       subject = iter.next();
       if(subject.startsWith("6.")){//将以6.开头的字符串从序列中移除
           iter.remove();
       }
}    

 

foreach语句格式:

  for(元素类型type  元素变量value : 遍历对象obj) { 

    引用value的语句;  

}

2.foreach过程分析

foreach内部调由迭代器实现,但是当需要删除序列元素时,foreach循环会发生错误

如:

分析:

ConcurrentModificationException异常

Iterator next方法实现源码:

public E next() {
    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();
}

在next方法中首先调用了checkForComodification方法,该方法会判断modCount是否等于expectedModCount,不等于就会抛出java.util.ConcurrentModificationExcepiton异常。

注:modCount是ArrayList的一个属性,继承自抽象类AbstractList,用于表示ArrayList对象被修改次数(add、remove、clear、ensureCapacityInternal均会改变modCount值)。在创建Iterator的时候会将modCount赋值给expectedModCount,之后expectedModCount不再改变。设置该检查的目的是为了阻止程序员在不允许修改的时候修改对象,Iterator 被创建之后会建立一个指向原来对象的单链索引表,当原来的对象数量发生变化时,这个索引表的内容不会同步改变。 当索引指针往后移动的时候就找不到要迭代的对象,所以禁止迭代时修改对象,于是会抛出错误。

在执行next方法时,将会检查modCount与expectedModCount值,由于foreach方法中,其内部由iterator实现,也会调用next()方法,但是,每次删除元素时均会改变modCount值,因此,调用序列自身的remove()方法后再次调用next()方法时,经检查modCount != expectedModCount,因此抛出ConcurrentModificationException异常

  然而,在使用迭代器时,对迭代中的元素进行删除并不会抛出错误,原因是:在iterator.remove()方法中,同样调用了ArrayList自身的remove方法,但是调用完之后并非就return了,而是expectedModCount = modCount重置了expectedModCount值,使二者的值继续保持相等。同时,Iterator.remove() 方法会在删除当前迭代对象的同时维护索引的一致性,不会导致索引指针移动时找不到迭代对象。

下面使用迭代器的语句同样会抛出ConcurrentModificationException异常:

 

Iterator iter  = subjects.iterator();
while(iter.hasNext()){
       subject = iter.next();
       if(subject.startsWith("6.")){
           subjects.remove(subject);//仅将iter.remove()更改为subjects.remove(subject)
       }
}    

 

可以看出,异常确实是由迭代器在迭代过程中抛出

 

 

参考:

1.Java中Iterator用法整理

2.java.util.ConcurrentModificationException 异常问题详解

3.ConcurrentModificationException迭代集合删除元素!!

posted @ 2018-03-21 23:05  always_new  阅读(3901)  评论(0编辑  收藏  举报