Why having a short-circuiting operation in the pipeline is necessary... in Java 8

Viewed 1365

I read this api doc Stream api and it says ( three sentences in a paragraph )

"An intermediate operation is short-circuiting if, when presented with infinite input, it may produce a finite stream as a result."

"A terminal operation is short-circuiting if, when presented with infinite input, it may terminate in finite time."

"Having a short-circuiting operation in the pipeline is a necessary, but not sufficient, condition for the processing of an infinite stream to terminate normally in finite time."

  1. I don't understand why intermediate and terminal operations are short-circuiting if, when presented with infinite input.

  2. I don't understand third sentence as well why short-circuiting is necessary but insufficient condition for processing infinite stream to terminate normally in finite time.

It would be great if someone helps me to understand with a code example.

What I know about short-circuiting is like

for example, if( a && b ) { ... } if a is false, you don't have to check b.

2 Answers

I don't understand why intermediate and terminal operations are short-circuiting if, when presented with infinite input.

Because it is stated that "An intermediate operation is short-circuiting if, when presented with infinite input, it may produce a finite stream as a result."

Example: limit() if its input is an infinite stream the output is finite and then there is no necessity to try to consume all the input, so it is short-circuit because it produces an output in finite time even if the input can not be processed in finite time.

Stream<Integer> infiniteStream = Stream.iterate(0, i -> i + 1);
infiniteStream.limit(5).forEach(System.out::println);

produces an output and terminates in finite time even if the infiniteStream is infinite.

I don't understand third sentence as well why short-circuiting is necessary but insufficient condition for processing infinite stream to terminate normally in finite time.

Sentence is : "Having a short-circuiting operation in the pipeline is a necessary, but not sufficient, condition for the processing of an infinite stream to terminate normally in finite time."

Example : anyMatch is a short-circuiting terminal operation but produces a result on an infinite stream only if a element of the input stream verifies the predicate.

Stream<Integer> infiniteStream = Stream.iterate(0, i -> i);
infiniteStream.anyMatch(x->x==1).forEach(System.out::println);

does not terminates but :

Stream<Integer> infiniteStream = Stream.iterate(0, i -> i);
infiniteStream.anyMatch(x->x==0).forEach(System.out::println);

does.

Short-circuiting in logical expressions is another kind of short-circuiting but you can consider what happens on expression like if (f() && g()) with f and/or g has infinite computations... Question: when does the expression can have a value? If f() produces false then even if g() is an infinite computation the expression equals to false. Then in some way, && can short-cut some infinite computations.

In the context of Stream and as the doc already suggests the short-circuiting operations are limit(n), findFirst() etc.

Short-circuiting operations such as limit(n) or findFirst() can allow computations on infinite streams to complete in finite time.

e.g.

Stream stream;
stream.forEach(s -> {..do something}); // something is executed until all the elements of source are traversed
stream.limit(n).forEach(s -> {do something else}); // something else is executed just for 'n' times
Related