Java .foreach和.stream().foreach之间有什么区别?
这是一个例子: 代码A: 另一个代码B可以这样使用: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.
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 -> { });