Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is Stream.findAny a short-circuit operation?

Consider this code

Object found = collection.stream()
    .filter( s -> myPredicate1(s))
    .filter( s -> myPredicate2(s))
    .findAny()

Will it process entire stream, and call both myPredicate1 and myPredicate2 for all elements of the collection? Or will as many predicates be called as are needed to actually find the value?

like image 390
Dariusz Avatar asked May 25 '17 12:05

Dariusz


People also ask

What is short circuiting operation on a stream?

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.

Which is a short circuiting immediate operation in Java stream?

The terminal short-circuit operations in stream are findFirst(), findAny(), allMatch(), anyMatch(), and noneMatch().

Which of the following are short circuit operations in Java?

So when Java finds the value on the left side of an || operator to be true, then Java declares the entire expression to be true. Java's && and || operators use short circuit evaluation. Java's & and | operators also test for the "and" and "or" conditions, but these & and | operators don't do short circuit evaluation.

Does anyMatch short circuit?

Short Circuiting The fundamental difference between anyMatch() and count() is that anyMatch() is short-circuiting which means it will stop at the first match whereas count() will count all matches before returning.


1 Answers

Yes it is, as the Stream.findAny() documentation states:

This is a short-circuiting terminal operation.

It's a common misconception that objects in stream are "pushed" towards consuming operation. It's actually the other way around - the consuming operation pulls each element.

For sequential streams only as many predicates will be called as are needed to find matching value. Parallel streams may execute more predicates, but will also stop execution as soon as an element is found.

public class StreamFilterLazyTest {

  static int stI = 0;

  static class T { 

    public T() {
      super();
      this.i = ++stI;
    }

    int i;

    int getI() {
      System.err.println("getI: "+i);
      return i;
    }
  }

  public static void main(String[] args) {
    T[] arr = {new T(), new T(), new T(), new T(), new T(), new T(), new T(), new T(), new T(), new T()};
    Optional<T> found = Arrays.stream(arr).filter(t -> t.getI() == 3).findAny();
    System.out.println("Found: "+found.get().getI());
  }
}

will print:

getI: 1
getI: 2
getI: 3
Found: 3
like image 84
Dariusz Avatar answered Sep 27 '22 23:09

Dariusz