2014-01-31 239 views
7

我經常遇到這樣的情況,我想爲某個對象的某個Collection或數組使用enchanced for循環。增強for循環

例如

items = basket.getItems(); 
for (int item : items) { 
    // Do something 
} 

另一種方法是:

for (int item : basket.getItems()) { 
    // Do something 
} 

第二個是更緊湊,在我看來,提高了可讀性,尤其是當item變量不會被其他任何地方使用。

我想知道for語句中的getter是否對性能有任何影響。它會被優化成與第一個類似的東西嗎?或者每次都會訪問getter?當然,getItems()可能會做一些很慢的事情(例如網絡訪問等)

問題與其他一些類似,但是指的是集合/數組本身的getter,而不是它的大小。但最終可能會出現同樣的情況。

+0

你爲什麼不測試它?只需在該吸氣器中放置一個「println」即可。 –

+0

在我的特定配置和特定對象中進行測試不會產生正確的答案,因爲對我的具體結果進行概括會是錯誤的 – LyK

+0

@tobias_k,好的想法。但是在理論上可能會(當然)編譯器不會用引用替換調用'basket.getItems()',而實際上該方法不僅僅是返回一個引用嗎? – GameDroids

回答

9

在這兩種情況下,getItems()方法只會被調用一次。兩者之間沒有區別,除了使用額外的局部變量,你可以在別的地方使用。

正如你可以在JLS 14.14.2讀,增強循環大致轉換爲這種傳統的for循環:

for (I #i = Expression.iterator(); #i.hasNext();) { 
    TargetType Identifier = (TargetType) #i.next(); 
    Statement 
} 

#i中是自動生成的標識符是從任何其他標識符不同的(自動生成的或以其他方式)在範圍內(第6.3節)發生增強型for語句時。

從這裏可以明顯看出Expression僅被評估一次。

0

是的第二個提高了代碼的可讀性。

如果您從網絡中獲取對象,然後在for循環中迭代它,那麼我認爲它會對性能產生影響,因爲您每次都在訪問網絡,而且對於小型/單個對象的操作不建議網絡訪問。而不是從網絡訪問中獲取一次將其存儲在本地並迭代它

因此,第一個選項是網絡訪問情況下的性能優化 如果您的對象是本地的,那麼任何方法都可以。不會有太大的表現差異。

2

正如您在以下代碼示例中所看到的那樣,在增強功能上,迭代的集合的初始化只完成一次。所以,第二種選擇更加緊湊,並且不會影響性能。

package test; 

public class Main { 

     static class Basket { 
      int[] items = { 1, 2, 3 }; 

     public int[] getItems() { 
       System.out.println("in getItems()"); 
      return items; 
     } 

    } 

    public static void main(String[] args) { 
     Basket basket = new Basket(); 
     for (int item : basket.getItems()) { 
      System.out.println(item); 
     } 

    } 
} 
0

我不認爲它會每次調用getter。如果它確實會每次都會得到新的列表,並且Loop不會中斷。您可以通過將簡單的Sysout放在getter方法中進行測試。這兩種情況下的性能會相同。