我在书上看到,  如果获得容器对象的迭代器以后,改变了原容器中的数据,之后使用迭代器会失败。所以,在获取迭代器之后,不要对容器做任何修改。
但是我 修改了容量,为什么不报错。
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class OperArrayListDemo {

public static void arrayListOne()
{
ArrayList lst=new ArrayList();
lst.add("aa");
lst.add(5);
lst.add("bb");
String a=(String)lst.get(0).toString();
//System.out.println(a);
//displayListOne(lst);
displayListTwo(lst);
lst.add("cc");
displayListOne(lst);
}

public static void displayListOne(List list)
{
for(int i=0;i<list.size();i++)
{
System.out.println(list.get(i).toString());
}
}


/*
 * 通过迭代器输出
 */

public static void displayListTwo(List list)
{
Iterator iterator=list.listIterator();
while(iterator.hasNext())
{
System.out.println(iterator.next());
}

}



public static void main(String args[])
{
arrayListOne();

}

}

解决方案 »

  1.   

    下面代码试图在迭代的时候进行修改,抛出运行时异常了:import java.util.ArrayList;
    import java.util.List;public class Test {
    public static void main(String[] args) {
    List<String> list = new ArrayList<String>();
    list.add("a");
    list.add("a");
    list.add("b");

    for(String s : list) {
    if(s.equals("b")) {
    list.add(s);
    }
    }
    }
    }个人觉得看一下Java Tutorial上面这方面的介绍很好。
      

  2.   

    应该是获得迭代器之后迭代之前对容器长度进行修改会报错吧
    package aa;import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    public class OperArrayListDemo {
        
        public static void arrayListOne()
        {
            ArrayList lst=new ArrayList();
            lst.add("aa");
            lst.add(5);
            lst.add("bb");
            String a=(String)lst.get(0).toString();
            //System.out.println(a);
            //displayListOne(lst);
            Iterator iterator =  displayListTwo(lst);
            lst.add("cc");
            while(iterator.hasNext())
            {
                System.out.println(iterator.next());
            }
            displayListOne(lst);
        }
        
        public static void displayListOne(List list)
        {
            for(int i=0;i<list.size();i++)
            {
                System.out.println(list.get(i).toString());
            }
        }
        
        
        /*
         * 通过迭代器输出
         */
        
        public static Iterator displayListTwo(List list)
        {
            Iterator iterator=list.listIterator();
            return iterator;
        }
        
        
        
        public static void main(String args[])
        {
            arrayListOne();
            
        }
        
        }
      

  3.   

    iterator模式是用于遍历集合类的标准访问方法。它可以把访问逻辑从不同类型的集合类中抽象出来,从而避免向客户端暴露集合的内部结构。首先看看java.util.Iterator接口的定义:view plaincopy to clipboardprint?
    01.public interface Iterator {   
    02.    boolean hasNext();   
    03.    Object next();   
    04.    void remove();   
    05.}  
    public interface Iterator {
        boolean hasNext();
        Object next();
        void remove();
    }
     每一种集合类返回的Iterator具体类型可能不同,Array可能返回ArrayIterator,Set可能返回SetIterator,Tree 可能返回TreeIterator,但是它们都实现了Iterator接口,因此,客户端不关心到底是哪种Iterator,它只需要获得这个 Iterator接口即可,这就是面向对象的威力。让我们来看看AbstracyList如何创建Iterator。首先AbstractList定义了一个内部类(inner class):
    view plaincopy to clipboardprint?
    01.private class Itr implements Iterator {   
    02.    ...   
    03.}   
    private class Itr implements Iterator {
        ...
    }  而iterator()方法的定义是:view plaincopy to clipboardprint?
    01.public Iterator iterator() {   
    02.    return new Itr();   
    03.}  
    public Iterator iterator() {
        return new Itr();
    }
     因此客户端不知道它通过Iterator it = a.iterator();所获得的Iterator的真正类型。现在我们关心的是这个申明为private的Itr类是如何实现遍历AbstractList的:view plaincopy to clipboardprint?
    01.private class Itr implements Iterator {   
    02.    int cursor = 0;   
    03.    int lastRet = -1;   
    04.    int expectedModCount = modCount;   
    05.}  
    private class Itr implements Iterator {
        int cursor = 0;
        int lastRet = -1;
        int expectedModCount = modCount;
    }
     Itr类依靠3个int变量(还有一个隐含的AbstractList的引用)来实现遍历,cursor是下一次next()调用时元素的位置,第一次调用next()将返回索引为0的元素。lastRet记录上一次游标所在位置,因此它总是比cursor少1。变量cursor和集合的元素个数决定hasNext():view plaincopy to clipboardprint?
    01.public boolean hasNext() {   
    02.    return cursor != size();   
    03.}  
    public boolean hasNext() {
        return cursor != size();
    } 方法next()返回的是索引为cursor的元素,然后修改cursor和lastRet的值:view plaincopy to clipboardprint?
    01.public Object next() {   
    02.    checkForComodification();   
    03.    try {   
    04.        Object next = get(cursor);   
    05.        lastRet = cursor++;   
    06.        return next;   
    07.    } catch(IndexOutOfBoundsException e) {   
    08.        checkForComodification();   
    09.        throw new NoSuchElementException();   
    10.    }   
    11.}  
        public Object next() {
            checkForComodification();
            try {
                Object next = get(cursor);
                lastRet = cursor++;
                return next;
            } catch(IndexOutOfBoundsException e) {
                checkForComodification();
                throw new NoSuchElementException();
            }
        }
     expectedModCount表示期待的modCount值,用来判断在遍历过程中集合是否被修改过。AbstractList包含一个 modCount变量,它的初始值是0,当集合每被修改一次时(调用add,remove等方法),modCount加1。因此,modCount如果不变,表示集合内容未被修改。Itr初始化时用expectedModCount记录集合的modCount变量,此后在必要的地方它会检测modCount的值:view plaincopy to clipboardprint?
    01.final void checkForComodification() {   
    02.    if (modCount != expectedModCount)   
    03.        throw new ConcurrentModificationException();   
    04.}  
        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
     如果modCount与一开始记录在expectedModeCount中的值不等,说明集合内容被修改过,此时会抛出ConcurrentModificationException。这个ConcurrentModificationException是RuntimeException,不要在客户端捕获它。如果发生此异常,说明程序代码的编写有问题,应该仔细检查代码而不是在catch中忽略它。但是调用Iterator自身的remove()方法删除当前元素是完全没有问题的,因为在这个方法中会自动同步expectedModCount和modCount的值:view plaincopy to clipboardprint?
    01.public void remove() {   
    02.    ...   
    03.    AbstractList.this.remove(lastRet);   
    04.    ...   
    05.    // 在调用了集合的remove()方法之后重新设置了expectedModCount:   
    06.    expectedModCount = modCount;   
    07.    ...   
    08.}  
        public void remove() {
            ...
            AbstractList.this.remove(lastRet);
            ...
            // 在调用了集合的remove()方法之后重新设置了expectedModCount:
            expectedModCount = modCount;
            ...
        }
     要确保遍历过程顺利完成,必须保证遍历过程中不更改集合的内容(Iterator的remove()方法除外),因此,确保遍历可靠的原则是只在一个线程中使用这个集合,或者在多线程中对遍历代码进行同步。
    http://blog.csdn.net/aj_zLc/archive/2010/10/30/5976202.aspx