2012-02-10 50 views
21

(對於那些誰熟悉的JVM編譯和優化技巧的一個問題... :-)Java循環效率(「爲」與「的foreach」)

是否有任何的「對」與「 foreach「模式明顯優於其他模式?

考慮下面兩個例子:

public void forLoop(String[] text) 
{ 
    if (text != null) 
    { 
     for (int i=0; i<text.length; i++) 
     { 
      // Do something with text[i] 
     } 
    } 
} 

public void foreachLoop(String[] text) 
{ 
    if (text != null) 
    { 
     for (String s : text) 
     { 
      // Do something with s, exactly as with text[i] 
     } 
    } 
} 

forLoop更快或比foreachLoop慢?

假設在這兩種情況下,text陣列都不需要進行任何智能檢查,是否有明顯的贏家或仍然太接近打電話?

編輯:正如在一些答案中指出的,數組的性能應該是相同的,而「foreach」模式對於像列表這樣的抽象數據類型可能稍微好一些。另見this answer,其中討論了這個問題。

+0

回答256859確實覆蓋了我的問題,但不知怎的,它並沒有在我做的搜索中彈出。感謝大家! – PNS 2012-02-10 11:23:29

回答

55

section 14.14.2 of the JLS

否則,表達式必須具有一個數組類型,T []。讓L1 ... Lm是緊接在增強for語句之前的(可能是空的)標籤序列。然後,增強的for語句的含義是由以下幾個基本的語句中給出:

T[] a = Expression; 
L1: L2: ... Lm: 
for (int i = 0; i < a.length; i++) { 
     VariableModifiersopt Type Identifier = a[i]; 
     Statement 
} 

換句話說,我希望他們最終會被編譯成相同的代碼。

肯定有一個明顯的贏家:增強型for循環是更具可讀性。這應該是你的主要關注點 - 當你證明最可讀的表單不能很好地執行時,你應該只考慮微觀優化這類事情。

+10

+1強調可讀性/可理解性的重要性! – jbranchaud 2012-02-15 14:09:54

1

由於您使用的是array類型,因此性能差異無關緊要。在通過optimization漏斗後,他們最終會獲得相同的性能。

但是,如果您使用ADT如List,那麼forEachLoop顯然是與多個get(i)調用相比的最佳選擇。

+1

加上是的,你不應該依賴這種'優化'細節,你可以隨時失望。 – 2012-02-10 10:51:59

3

除非您知道自己有性能問題,否則幾乎每次都應該選擇更易讀的選項。

在這種情況下,我會說他們保證是一樣的。

唯一的區別是你額外檢查text.length這可能會更慢,而不是更快。

我也確保文本不會靜態爲空。例如使用@NotNull註釋。它更好地在編譯/編譯時捕獲這些問題(並且它會更快)

1

使用for-each循環,即使對於數組,也沒有性能損失。實際上,在某些情況下,它可能會比普通的for循環提供輕微的性能優勢,因爲它僅計算一次數組索引的限制。有關詳情,請參閱此post

4

您可以編寫自己的測試執行時間的簡單測試。

long start = System.currentTimeMillis(); 
forLoop(text); 
long end = System.currentTimeMillis(); 
long result = end - start; 

結果是執行時間。

+0

似乎是的,但實際上有太多影響這種測量的其他參數(甚至執行測試的順序)認爲它是可靠的。 – PNS 2012-02-10 11:29:57

+2

是的,測量執行時間並且應該具有一定程度的有效性的測試永遠不是「簡單的」。 – Bombe 2012-02-10 12:21:01

+0

@PNS:衡量(在現實情況下)比猜測更好。通過測量,你只能被誤導;有猜測,你可以去_wildly_錯誤。 – 2012-02-15 14:22:31