Here you have two stream pipelines.
These stream pipelines consist of a source, several intermediate operations, and terminal operations.
But intermediate operations are lazy. This means that nothing happens if the item is not required for the downstream operation. When this happens, the intermediate operation does everything necessary to create the required element, and then waits again until another element is requested, etc.
Terminal operations are usually "impatient." That is, they request all the elements in the stream that are needed to complete them.
So, you should really think of the pipeline as forEach , requesting a stream behind it for the next element, and that stream will request a stream behind it, etc. down to the source.
With this in mind, let's see what we have with your first pipeline:
Stream.of(1,2,3,4,5,6,7,8,9) .peek(x->System.out.print("\nA"+x)) .limit(3) .peek(x->System.out.print("B"+x)) .forEach(x->System.out.print("C"+x));
So forEach requests the first element. This means that the "B" peek needs an element and requests the limit output stream for it, which means that limit will need to request the "A" peek , which goes to the source. The element is given and comes to forEach , and you will get your first line:
A1B1C1
forEach requests another element, then another. And each time the request is propagated upstream and executed. But when forEach requests the fourth element, when the request falls into limit , he knows that he has already provided all the elements that he is allowed to give.
Thus, it does not query “A” for another element. It immediately indicates that its elements are exhausted, and thus no more actions are performed and forEach completed.
What happens in the second pipeline?
Stream.of(1,2,3,4,5,6,7,8,9) .peek(x->System.out.print("\nA"+x)) .skip(6) .peek(x->System.out.print("B"+x)) .forEach(x->System.out.print("C"+x));
Again, forEach requests the first element. It spreads back. But when he gets to skip , he knows that he needs to ask for 6 items from his upstream before he can transfer one downstream. Thus, he makes a request upstream from the “A” peek , consumes it without passing it downstream, makes another request, and so on. Thus, viewing "A" receives 6 requests for an element and produces 6 prints, but these elements are not transmitted.
A1 A2 A3 A4 A5 A6
In the 7th request made by skip , the element is passed to "B" and from it to forEach , so full printing is performed:
A7B7C7
Then it is exactly the same as before. skip now, whenever it receives a request, it requests the element up and passes it downstream, as it “knows” that it has already completed its work on skipping. Thus, the remaining prints pass through the entire pipe until the source is exhausted.