What is the difference between .foreach and .strea

2020-02-26 07:06发布

问题:

This is a example: code A:

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

and another code B may use on this way:

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

What is the difference between both, with stream() and no stream()?

回答1:

Practically speaking, they are mostly the same, but there is a small semantic difference.

Code A is defined by Iterable.forEach, whereas code B is defined by Stream.forEach. The definition of Stream.forEach allows for the elements to be processed in any order -- even for sequential streams. (For parallel streams, Stream.forEach will very likely process elements out-of-order.)

Iterable.forEach gets an Iterator from the source and calls forEachRemaining() on it. As far as I can see, all current (JDK 8) implementations of Stream.forEach on the collections classes will create a Spliterator built from one of the source's Iterators, and will then call forEachRemaining on that Iterator -- just like Iterable.forEach does. So they do the same thing, though the streams version has some extra setup overhead.

However, in the future, it's possible that the streams implementation could change so that this is no longer the case.

(If you want to guarantee ordering of processing streams elements, use forEachOrdered() instead.)



回答2:

There is no difference in terms of semantics, though the direct implementation without stream is probably slightly more efficient.



回答3:

A stream is an sequence of elements (i.e a data structure) for using up an operation or iteration. Any Collection can be exposed as a stream. The operations you perform on a stream can either be

Intermediate operations (map, skip, concat, substream, distinct, filter, sorted, limit, peek..) producing another java.util.stream.Stream but the intermediate operations are lazy operations, which will be executed only after a terminal operation was executed.

And the Terminal operations (forEach, max, count, matchAny, findFirst, reduce, collect, sum, findAny ) producing an object that is not a stream.

Basically it is similar to pipeline as in Unix.



回答4:

Both approaches uses the terminal operation Iterable.forEach, but the version with .stream() also unnecessarily creates a Stream object representing the List. While there is no difference, it is suboptimal.