Faraz
Faraz

Reputation: 6285

Java 8 Streams intermediate operations produce new streams?

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

Answers (3)

Hossein Mobasher
Hossein Mobasher

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

Jason
Jason

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

Mureinik
Mureinik

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

Related Questions