旧与新的foreach循环

时间:2013-07-02 12:59:40

标签: foreach lambda java-8 java-stream

在什么情况下,我们应该在JDK 8中使用旧的foreach循环而不是新的collection.forEach(),还是最好的做法是转换每个 foreach循环?是否存在重要的性能差异?

我能想到的唯一情况是,如果你想迭代数组而不想先将数组转换为列表。

1 个答案:

答案 0 :(得分:2)

目前很难想到最佳实践,因为JDK 8尚未发布。但是,基于早期使用这些API,有一些有趣的观察结果。

forEach()方法现在位于Iterable,由Collection继承,因此所有集合都可以使用forEach()

数组可以包含在Arrays.asList()的集合中,也可以包含在Arrays.stream()的流中。这些只是包装纸;他们不会将所有元素复制到新容器中。

关于性能,Iterable.forEach(action)的默认实现只是通常的“增强的for-loop”,它创建一个迭代器并发出连续的hasNext()next()调用并调用{{ 1}}循环中的方法。与裸露的增强型for循环相比,额外的方法调用有一些额外的开销,但它可能非常小。

我会在风格上做出选择,而不是表现。

每个 enhanced-for循环转换为使用action可能不值得。考虑:

forEach()

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

如果lambda是真正的单行,那么它可能是值得的,但在我看来,coll.forEach(s -> { System.out.println("---"); System.out.println(s); System.out.println("---"); }); 中的多行语句lambda并不比一个好的for循环更清晰。

但是,如果for循环的主体中有逻辑,或者它需要保持某种运行状态,那么将循环重新转换为流管道可能是值得的。请考虑此片段,该片段可查找集合中最长字符串的长度:

forEach()

使用lambdas和流库重写,它看起来像这样:

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

当然,这是新的,不熟悉的,但在使用了一段时间之后,我发现它简洁易读。