2013-06-06 140 views
2
for(Element e : elementList) 

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

第一個簡單得多。我想做第二個有什麼優點或原因嗎?使用迭代器有什麼優勢?

+1

他們做同樣的事情,你可以使用第二個,當你想使用remove()方法。 –

+0

你測量了每個時間?這是一個技巧問題,其中一個方法有很多緩存命中,另一個有很多錯過? – Marichyasana

回答

4

它們在內部都使用迭代器,唯一的區別是當您使用增強for循環時代碼更清晰和更短。以下是javadoc對兩者所說的內容:

迭代集合比它需要的更醜。考慮以下方法,它需要定時器任務的集合並取消它們:

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

迭代器只是混亂。此外,這是一個錯誤的機會。迭代器變量在每個循環中出現三次:這是兩次錯誤的機會。 for-each構造擺脫了混亂和錯誤的機會。下面是該示例的外觀與for-each結構:「在」「在C每個TimerTask的T」

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

當你看到冒號(:)它讀成環路上面寫明作爲你可以看到,for-each構造與泛型完美地結合在一起。它保留了所有類型的安全性,同時消除了剩餘的雜波。因爲您不必聲明迭代器,所以不必爲其提供通用聲明。 (編譯器爲您完成此你背後,但你不必用它關心自己)

有關爲什麼我們要使用for-each循環,而不是迭代器完整的描述,請閱讀本:

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

2

第一種形式是在Java 5中引入的,第二種形式主要是在早期版本的語言的舊代碼中找到的。儘管如此,仍然有幾種情況你仍然需要使用第二種形式;例如,如果循環需要在迭代時刪除一些(或全部)元素,那麼您需要具有itr,因此您可以調用它的remove方法。

0

沒有性能上的差異來完成的元素。但通過使用迭代器,您將可以使用更多的功能。例如,你可以在循環中引用迭代器。這允許您執行諸如刪除收集項目的操作,獲得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

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 

拆解和得到以下字節碼的主要方法

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行是第二個循環。你會注意到它們幾乎是一樣的 - 只是一些當地人的名字改變了,並且輕微的重新排序。

因此,由於編譯器爲兩個表達式產生相同的字節碼,它們是相同的。

相關問題