使用迭代器有什么好处?

时间:2013-06-06 01:22:30

标签: java loops

for(Element e : elementList)

for (Iterator<Element> itr = elementList.iterator(); itr.hasNext();)

第一个更简单。我想做第二个有什么优点或理由吗?

5 个答案:

答案 0 :(得分:4)

在内部,它们都使用迭代器,唯一的区别是当你使用增强的for循环时,代码更清晰,更短。以下是javadoc对两者的说法:

迭代一个集合比它需要的更加丑陋。考虑以下方法,该方法接受一组计时器任务并取消它们:

void cancelAll(Collection<TimerTask> c) {
    for (Iterator<TimerTask> i = c.iterator(); i.hasNext(); )
        i.next().cancel();
}

迭代器只是杂乱无章。此外,这是一个错误的机会。迭代器变量在每个循环中出现三次:这是两次错误的机会。 for-each构造摆脱了混乱和错误的机会。以下是for-each构造的示例:

void cancelAll(Collection<TimerTask> c) {
    for (TimerTask t : c)
        t.cancel();
}

当你看到冒号(:)将其读作“in”时,上面的循环读作“对于c中的每个TimerTask t”。正如你所看到的,for-each构造与泛型完美结合。它保留了所有类型的安全性,同时消除了剩余的杂乱。因为您不必声明迭代器,所以您不必为它提供通用声明。 (编译器会在你背后为你做这件事,但你不必担心它。)

有关为什么我们应该使用for-each循环而不是迭代器的完整描述,请阅读:

http://docs.oracle.com/javase/1.5.0/docs/guide/language/foreach.html

答案 1 :(得分:2)

第一种形式是在Java 5中引入的,第二种形式主要在早期版本的语言的遗留代码中找到。尽管如此,在某些情况下您仍然需要使用第二种形式;例如,如果循环需要能够在迭代时删除一些(或全部)元素,那么您需要itr,以便可以调用其remove方法。 / p>

答案 2 :(得分:1)

Iterator可以remove()来自集合的元素,这不能用于每个循环

答案 3 :(得分:0)

没有性能差异。但是通过使用迭代器,您将拥有更多功能。例如,您可以在循环中引用Iterator。这使您可以执行删除收集项ConcurrentModificationException

之类的操作

您可以使用以下

for (Iterator<Element> itr = elementList.iterator(); itr.hasNext();){
     if(o meets some condition){
          itr.remove();
     }
}

但不是这个

   for(Element e : elementList){
         if(o meets some condition){
              elementList.remove(e);
         }
    }

但如果这种差异不打扰你,那么你可以使用那个安慰你的。

similar so question

答案 4 :(得分:0)

它们非常相似。考虑一下这段代码

import java.util.Iterator;
import java.util.ArrayList;

public class IteratorTest {

  public static void main(String[] args){

    ArrayList<Object> list = new ArrayList();
    list.add(new Object());
    list.add(new Object());

    for(Object o : list) 
      System.out.println(o);

    for(Iterator<Object> itr = list.iterator();itr.hasNext();) 
      System.out.println(itr.next());


  }
}

然后我们编译它并使用

反汇编它
javap -c IteratorTest

并获取main方法的以下字节码

  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: new           #4                  // class java/lang/Object
      12: dup           
      13: invokespecial #1                  // Method java/lang/Object."<init>":()V
      16: invokevirtual #5                  // Method java/util/ArrayList.add:(Ljava/lang/Object;)Z
      19: pop           
      20: aload_1
      21: new           #4                  // class java/lang/Object
      24: dup           
      25: invokespecial #1                  // Method java/lang/Object."<init>":()V
      28: invokevirtual #5                  // Method java/util/ArrayList.add:(Ljava/lang/Object;)Z
      31: pop           
      32: aload_1       
      33: invokevirtual #6                  // Method java/util/ArrayList.iterator:()Ljava/util/Iterator;
      36: astore_2      
      37: aload_2       
      38: invokeinterface #7,  1            // InterfaceMethod java/util/Iterator.hasNext:()Z
      43: ifeq          63
      46: aload_2       
      47: invokeinterface #8,  1            // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      52: astore_3      
      53: getstatic     #9                  // Field java/lang/System.out:Ljava/io/PrintStream;
      56: aload_3       
      57: invokevirtual #10                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      60: goto          37
      63: aload_1       
      64: invokevirtual #11                 // Method java/util/ArrayList.iterator:()Ljava/util/Iterator;
      67: astore_2      
      68: aload_2       
      69: invokeinterface #7,  1            // InterfaceMethod java/util/Iterator.hasNext:()Z
      74: ifeq          92
      77: getstatic     #9                  // Field java/lang/System.out:Ljava/io/PrintStream;
      80: aload_2       
      81: invokeinterface #8,  1            // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      86: invokevirtual #10                 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      89: goto          68
      92: return        
}

第32到60行是第一个循环,第63到89行是第二个循环。你会注意到它们几乎是一样的 - 只是改变了一些当地人的名字并进行了轻微的重新排序。

因此,由于编译器为两个表达式生成相同的字节码,因此它们是相同的。