Reputation: 6285
When I invoke intermediate operations on streams, do they create new stream for each intermediate operation?
List<Integer> list = List.of(1,2,3,4,5);
list.stream().filter(i -> i > 4).map(o -> o*2).collect(Collectors.toList());
How many streams did it create? 1 or 3?
Upvotes: 4
Views: 979
Reputation: 4472
Basically, one of the concepts of functional programming is pure functions
that deterministic and have no-side effect that called immutability
. All of the intermediate operations in the Stream
api are immutable and returns new Stream.
As mentioned in the Oracle
document, all of the intermediate operations like filter
, map
and etc returns new stream. For example document of map
method is as follow:
Stream<R> map(Function<? super T,? extends R> mapper)
Returns a stream consisting of the results of applying the given function to the elements of this stream. This is an intermediate operation.
Type Parameters: R - The element type of the new stream Parameters:
mapper - a non-interfering, stateless function to apply to each element
Returns: the new stream
For more information, you can take a look at the Stream implementation in Java (For example map
method that returns a new StatelessOp
)
public final <R> Stream<R> map(Function<? super P_OUT, ? extends R> mapper) {
Objects.requireNonNull(mapper);
return new StatelessOp<P_OUT, R>(this, StreamShape.REFERENCE,
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
@Override
Sink<P_OUT> opWrapSink(int flags, Sink<R> sink) {
return new Sink.ChainedReference<P_OUT, R>(sink) {
@Override
public void accept(P_OUT u) {
downstream.accept(mapper.apply(u));
}
};
}
};
}
Upvotes: 3
Reputation: 5244
Yes, the call to filter and map both create a new StatelessOp which is a new ReferencePipeline that implements the Stream interface. You are creating 3 new StatelessOp objects.
Upvotes: 2
Reputation: 312219
In a word - yes. Every call to such a method creates another Stream
object. You could see this if you broke down the chain and assigned these intermediate operations to variables as you go long:
Stream<Integer> s1 = list.stream();
System.out.println(System.identityHashCode(s1));
Stream<Integer> s2 = s1.filter(i -> i > 2);
System.out.println(System.identityHashCode(s2));
Stream<Integer> s3 = s2.map(o -> o*2);
System.out.println(System.identityHashCode(s3));
List<Integer> result = s3.collect(Collectors.toList());
System.out.println(result);
Sample output:
1163157884
1747585824
1149319664
[6, 8, 10]
Upvotes: 2