java - Java8容器 `for each`和Stream `for each`有什么区别

标签 java java-8 iteration

我知道我们可以使用 List.foreach 遍历,我们也可以使用List.stream.foreach来遍历。我不明白在 Java8 中遍历哪个更好。

最佳答案

forEach(Consumer) 方法在 Iterable 中声明CollectionList 扩展的接口(interface)。 forEach(Consumer) 的默认实现是:

default void forEach(Consumer<? super T> action) {
    Objects.requireNonNull(action);
    for (T t : this) {
        action.accept(t);
    }
}

如您所见,默认实现只是在 for-each 循环中调用 action。 for-each 循环只是语法糖:

for (Iterator<?> iterator = iterable.iterator(); iterator.hasNext(); ) {
    Object element = iterator.next();
    // Do what you need to with element
} 

除非您无权访问 for-each 循环中的 Iterator

Iterable 的特定实现可能会改变它实际迭代其元素的方式(它可能使用也可能不使用 Iterator)但它几乎总是 归结为一些 forwhile 循环。我说“几乎总是”是因为可能涉及某种类型的递归或链接。

现在,当您只是尝试迭代 List 时,使用 List.stream().forEach(Consumer) 会创建一个不必要的 Stream 对象> 按顺序。如果您确实需要以管道方式处理元素集合(例如映射、过滤、映射更多等等),您应该只使用流式 API。

因此,对于简单的迭代,使用 List.stream().forEach(Consumer) 的性能将低于简单的 List.forEach(Consumer) 调用在几乎所有情况下。性能提升很可能可以忽略不计,但“优化”并不过分是一个很容易解决的问题;特别是如果你一开始就没有犯“错误”。不要创建不需要的对象。

虽然简单地使用 for-each 循环而不是 forEach(Consumer) 可能会更好。它比功能更强大的对应物更容易阅读。


编辑

正如 Holger 在评论中提到的,Stream.forEach(Consumer)Iterable.forEach(Consumer) 有一个相当大的区别:它不保证元素的相遇顺序。虽然 Iterable.forEach(Consumer) 的迭代顺序也没有为 Iterable 接口(interface)定义,但可以通过扩展接口(interface)(例如 List)。但是,当使用 Stream 时,无论 Stream 的来源如何,都无法保证顺序。

如果您希望在使用 Stream 时保证顺序,您必须使用 Stream.forEachOrdered(Consumer)

关于java - Java8容器 `for each`和Stream `for each`有什么区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50662697/

相关文章:

java - 将 Java 代码导入 Swift iOS 应用程序?

Java 8 根据列表部分的条件过滤列表

java - 如何在 String.replaceAll 中使用 RegEx 在搜索和替换时忽略中间字符

c# - 在最深的二叉树中查找元素的最佳解决方案是什么

javascript - 为什么使用 "for...in"进行数组迭代是一个坏主意?

java - 专家错误 : element dependency can not have character children

java - 使用java web/Java EE设计并行计算应用程序

lambda - Sonar : lambda - Remove useless curly braces around statement

c# - 为什么这不会产生幸运数字?

java - 如何使用 jruby 创建 servlet(使用 jetty 运行)?