关于java:.foreach和.stream()。foreach有什么区别?

What is the difference between .foreach and .stream().foreach?

本问题已经有最佳答案,请猛点这里访问。

这是一个例子:
代码A:

1
2
3
files.forEach(f -> {
    //TODO
});

而另一个代码B可能会以此方式使用:

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

stream()和没有stream()两者之间有什么区别?


实际上,它们基本上是相同的,但是语义上的差别很小。

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

Iterable.forEach从源获取一个Iterator并对其调用forEachRemaining()。据我所知,集合类上所有当前的Stream.forEach实现(JDK 8)将创建一个从源迭代器之一构建的Spliterator,然后将在该Iterator上调用forEachRemaining,就像。因此,尽管流版本具有一些额外的设置开销,但它们执行相同的操作。

但是,将来可能会改变流的实现,以致情况不再如此。

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


尽管没有stream的直接实现可能会稍微更高效,但是在语义方面没有区别。


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

中间操作(map,skip,concat,substream,distinct,filter,sorted,limit,peek ..)产生另一个java.util.stream.Stream,但是中间操作是惰性操作,只有在终端操作被执行后才执行被执行。

终端操作(forEach,max,count,matchAny,findFirst,reduce,collect,sum,findAny)产生的对象不是流。

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


两种方法都使用终端操作Iterable.forEach,但是带有.stream()的版本也不必要地创建表示List的stream对象。虽然没有差异,但它不是最佳的。