Java .foreach和.stream().foreach之间有什么区别?

Java .foreach和.stream().foreach之间有什么区别?,java,lambda,java-8,java-stream,Java,Lambda,Java 8,Java Stream,这是一个例子: 代码A: 另一个代码B可以这样使用: files.stream().forEach(f -> { }); 使用stream()和不使用stream()两者之间有什么区别?在语义方面没有区别,尽管不使用stream的直接实现可能稍微高效一些。流是一个元素序列(即数据结构)用于用完操作或迭代。任何集合都可以作为流公开。在流上执行的操作可以是 中间操作(映射、跳过、concat、子流、distinct、筛选、排序、限制、peek..)生成另一个java.util.stream.

这是一个例子: 代码A:

另一个代码B可以这样使用:

files.stream().forEach(f -> { });

使用
stream()
和不使用
stream()
两者之间有什么区别?

在语义方面没有区别,尽管不使用
stream
的直接实现可能稍微高效一些。

流是一个元素序列(即数据结构)用于用完操作或迭代。任何集合都可以作为流公开。在流上执行的操作可以是

中间操作(映射、跳过、concat、子流、distinct、筛选、排序、限制、peek..)生成另一个java.util.stream.stream,但中间操作是惰性操作,只有在执行了终端操作后才会执行

以及终端操作(forEach、max、count、matchAny、findFirst、reduce、collect、sum、findAny)生成的对象不是流


它基本上类似于Unix中的管道

这两种方法都使用终端操作
Iterable.forEach
,但是带有
.stream()
的版本也不必要地创建表示列表的
对象。虽然没有区别,但它是次优的。

实际上,它们基本相同,但有一点语义差异

代码A由Iterable.forEach定义,而代码B由Stream.forEach定义。
Stream.forEach
的定义允许以任何顺序处理元素,即使是顺序流也是如此。(对于并行流,
Stream.forEach
很可能会无序处理元素。)

Iterable.forEach
从源代码获取迭代器,并对其调用
forEachRemaining()
。据我所见,collections类上所有当前的
Stream.forEach
实现(JDK 8)都将创建一个从源迭代器之一构建的拆分器,然后在该迭代器上调用
foreachrestain
,就像
Iterable.forEach
一样。所以他们做同样的事情,尽管streams版本有一些额外的设置开销

然而,在未来,streams的实现可能会发生变化,因此情况不再如此


(如果您想保证处理流元素的顺序,请改用
forEachOrdered()

您的答案可能很有见地,但显然忽略了问题。这并不准确。两者在语义上都是等价的,但都不一定有这样的实现。代码A等于(文件f:文件)代码B应该在有一些中间操作(映射、跳过、concat、子流、distinct、filter、sorted、limit、peek..)时使用,否则它是次优的。谢谢大家!对不起,这不对。代码A确实是
Iterable.forEach
,但代码B是
Stream.forEach
,它不能保证以任何特定顺序处理元素,即使是顺序流也是如此。@Stuart:这是一个API细节,而StreamSupport自JDK 8以来对Iterable(数组除外)流使用底层Iterable.forEach。因此,您对执行差异的潜在担忧是不存在的。我的回答没有错。担心不可能是不存在的,区别也是。顺便说一句:是什么使得
Iterable.forEach
terminal?你声称“API细节”是为了证明你对实现细节的诉求是合理的,这非常有趣!你的说法完全错误;
Stream
中的
forEach
方法与
Iterable
中的方法无关。OracleJDK当前版本中的当前实现碰巧使用了
Iterable
one,但这基本上是不相关的,因为您不能指望它保持不变。您只能依赖API规范。
Stream.forEach
不使用当前实现调用
Iterable.forEach
。这很容易证明:
newarraylist(){@Override public void forEach(因实现的潜在更改而禁用的ConsumerUpvNoted可能会破坏当前的契约出乎意料的是,
Iterable的
default
实现。forEach
不会在
迭代器上调用
forEach
;它使用for each循环进行迭代。默认的
流。forEach
将调用
forEach剩余的
Spliterator
上,这将最终调用
Iterator.foreachrestining
,除非
Iterable.Spliterator()
已被重写(大多数JRE提供了
Collection
Collection.forEach(…)
Collection.stream().forEach(…)
基本上是一样的,它们以不同的代码结束。但是对于某些
集合
s,存在显著差异。
向量
集合返回的集合存在显著差异。同步…
方法,因为它们的
forEach
实现将是
同步的调用
stream().forEach(…)
需要手动同步。实际上,在语义方面存在差异,例如排序保证(或者在
stream.forEach
情况下没有)。
files.stream().forEach(f -> { });