Reputation: 8086
In Java 8 Stream API, description of an intermediate operation like filter
, map
and peek
is mentioned as
...elements of this stream...
But, stream intermediate operations like filter
seems to process and return an individual 'element' at a time. For example, Java 8 stream operations execution order question(see output) and answers.
The API descripton of filter
is
Returns a stream consisting of the elements of this stream that match the given predicate.
But, the code mentioned in Java 8 stream operations execution order question seems to process and return an individual element at a time. Please clarify the disconnect between API's mention of 'elements' and apparent processing of single 'element' of the code.
Thanks.
Upvotes: 5
Views: 933
Reputation: 56433
Yes, stateless intermediate operations such as filter
, map
etc. process a given element at a time and the former either does or does not send it on to the next stage where the next stage is the subsequent intermediate operation in the stream pipeline. the latter will always send the element to the subsequent operation after the mapping function is invoked.
for example:
...
.filter(n -> n % 2 == 0) // retain even numbers
.map(n -> n * n) // square it
...
one element at a time will pass through the filter
operation and if the current element meets the provided predicate it is then passed to the map
operation.
I think you understand this part, but rather your confusion is why in the java doc was it written:
Returns a stream consisting of the elements of this stream that match the given predicate.
"Returns a stream" because each intermediate operation returns a new stream.
"consisting of the elements" because a stream represents a sequence of elements and in the majority of the cases there are multiple elements that pass through a given intermediate operation.
this might sound like a stream stores its elements but this is not the case at all. Rather they may be stored in some underlying collection or generated on demand.
It's worth noting that not every intermediate operation will pass one element at a time to the next stage. for example the sorted
intermediate operation buffers all the elements until it sees the end of the input, and then it sends the data to the subsequent stage.
As a reading, there is a brilliant post by Brian Goetz regarding Streams under the hood. This really goes into details about streams and there is a good animation courtesy of Tagir Valeev that show how to visualize a stream.
Upvotes: 7
Reputation: 557
The map
and filter
intermediate operations are indeed executed on every single element of the stream, but they return a stream for themselves.
So, when we are looking at the code from the upper question, the filter operation will be executed with each number 1-8, but it will return a new stream which observes only the even numbers {2,4,6,8}.
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8);
List<Integer> twoEvenSquares = numbers.stream().filter(n -> {
System.out.println("filtering " + n);
return n % 2 == 0;
}).map(n -> {
System.out.println("mapping " + n);
return n * n;
}).limit(2).collect(Collectors.toList());
There is no disconnect because like the Stream 8 Stream API says, the intermediate operators like filter(Function<?, Boolean> filteringFunction)
return a Stream. They do this by executing the given filteringFunction
on every element of the in-stream and return a new out-stream which only observes the elements that have been filtered to true
.
Upvotes: 1
Reputation: 3894
I think there is some misunderstanding here because filter always return stream.
See signature for the same as below:
Stream<T> filter(Predicate<? super T> predicate);
So, any such intermediate operation returns the stream instead of one element at a time and you can execute all operations on them as you can execute on streams.
Same is the case with specification:
Returns a stream consisting of the elements of this stream that match the given predicate.
Upvotes: 3