在什么情况下,我们应该在JDK 8使用旧foreach
循环在新collection.forEach()
或者是转换每foreach
循环最好的做法?有没有重要的性能差异?老与新的foreach循环
我能想到的唯一情况是如果你想遍历一个数组,并且不想先将数组转换为列表。
在什么情况下,我们应该在JDK 8使用旧foreach
循环在新collection.forEach()
或者是转换每foreach
循环最好的做法?有没有重要的性能差异?老与新的foreach循环
我能想到的唯一情况是如果你想遍历一个数组,并且不想先将数组转换为列表。
由于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();
这是新的和不熟悉的当然,但经过这一段时间,我发现它简洁易读。
创建一个parallelStream()或一个stream()然后调用forEach的好处如何? – MohamedSanaulla
是的,使用流确实可以提供更简单的并行性。然而,最初的问题是关于'Collection.forEach'(真的,'Iterable.forEach'),它隐含地是连续的,有序的,并且有副作用。将每个循环改为并行流可能涉及很多工作,并不一定是一个简单的重构。 –
请注意,'forEach()'已移至'Iterable',但它仍由'Collection'继承。 –