2013-07-02 52 views
3

在什麼情況下,我們應該在JDK 8使用舊foreach循環在新collection.forEach()或者是轉換foreach循環最好的做法?有沒有重要的性能差異?老與新的foreach循環

我能想到的唯一情況是如果你想遍歷一個數組,並且不想先將數組轉換爲列表。

+0

請注意,'forEach()'已移至'Iterable',但它仍由'Collection'繼承。 –

回答

2

由於JDK 8還沒有發佈,所以現在很難考慮最佳實踐。但是,基於這些API的早期使用,有一些有趣的觀察。

forEach()方法現在在Iterable上,它由Collection繼承,所以所有集合都可以使用forEach()

一個數組可以用Arrays.asList()或與Arrays.stream()流合併在一個集合中。這些只是包裝;他們不會將所有元素複製到新的容器中。

關於性能的Iterable.forEach(action)默認的實現僅僅是通常的「增強的for循環」,它創建了一個迭代器和問題連續hasNext()next()調用和調用一個循環內的action方法。與裸增強for循環相比,額外方法調用有一點額外開銷,但它可能非常小。

我會選擇文體的理由,而不是性能。

可能不值得將轉換爲 enhanced-for循環使用forEach()。試想一下:

for (String s : coll) { 
    System.out.println("---"); 
    System.out.println(s); 
    System.out.println("---"); 
} 

coll.forEach(s -> { 
    System.out.println("---"); 
    System.out.println(s); 
    System.out.println("---"); 
}); 

如果拉姆達是一個真實的班輪它可能是值得的,但在我看來內forEach()多行語句拉姆達並不比更清晰一個很好的for循環。但是,如果for循環的主體中包含邏輯,或者如果它需要保持某種運行狀態,則可能需要將循環重新轉換爲流管道。考慮這個片段,發現一個集合中的最長的字符串的長度:

int longest = -1; 
for (String s : strings) { 
    int len = s.length(); 
    if (len > longest) 
     longest = len; 
} 

使用lambda表達式和流庫改寫,它應該是這樣的:

OptionalInt longest = 
    strings.stream() 
      .mapToInt(s -> s.length()) 
      .max(); 

這是新的和不熟悉的當然,但經過這一段時間,我發現它簡潔易讀。

+0

創建一個parallelStream()或一個stream()然後調用forEach的好處如何? – MohamedSanaulla

+1

是的,使用流確實可以提供更簡單的並行性。然而,最初的問題是關於'Collection.forEach'(真的,'Iterable.forEach'),它隱含地是連續的,有序的,並且有副作用。將每個循環改爲並行流可能涉及很多工作,並不一定是一個簡單的重構。 –