2013-07-02 49 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'),它隐含地是连续的,有序的,并且有副作用。将每个循环改为并行流可能涉及很多工作,并不一定是一个简单的重构。 –