[转]Java三种遍历集合的方式

foreach和迭代器模式

Posted by zhidaliao on May 22, 2015

Java的遍历集合方式主要有以下三种:

System.out.println("----------method1-----------");
for (int i = 0; i < list.size(); i++) {
    System.out.println(list.get(i));
}

System.out.println("----------method2-----------");
for (String s : list) {
    System.out.println(s);
    //ConcurrentModificationException,其实JAVA中的增强for循环底层是通过迭代器模式来实现的。
    //list.remove(s);
}

System.out.println("----------method3-----------");
Iterator iterator=list.iterator();
while(iterator.hasNext()){
    String s= (String) iterator.next();
    if(s.equals("value1")){
        //安全删除
        iterator.remove();
    }else{
        System.out.println(s);    
    }
}

运行方法2的时候,如果调用list.foreach方法,会报ConcurrentModificationException异常, 对以下代码反编译:

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

编译后的结果:

Integer i; 
for(Iterator iterator = list.iterator(); iterator.hasNext(); System.out.println(i)){ 
    i = (Integer)iterator.next();         
} 

可以看到foreach的实现其实是用了迭代器,利用迭代器在集合遍历是删除会报ConcurrentModificationException异常,所以需要使用迭代器自带的删除方法操作,如果遍历时候需要删除操作,使用第三种(method3)遍历方式。

Iterator是工作在一个独立的线程中,并且拥有一个 mutex 锁。 Iterator被创建之后会建立一个指向原来对象的单链索引表,当原来的对象数量发生变化时,这个索引表的内容不会同步改变,所以当索引指针往后移动的时候就找不到要迭代的对象,所以按照 fail-fast 原则 Iterator 会马上抛出java.util.ConcurrentModificationException异常。

所以 Iterator 在工作的时候是不允许被迭代的对象被改变的。但你可以使用 Iterator 本身的方法 remove() 来删除对象,Iterator.remove() 方法会在删除当前迭代对象的同时维护索引的一致性。

原文链接