java – Restrict a flow of a predicate

Such an operation should be possible with a Java 8 Streambut it may not necessarily be done efficiently – for example, you may need to parallelize it, as you need to look at the elements in order.

The API doesn’t provide an easy way to do this, but what is probably the simplest way is to take Stream.iterator()wrap Iterator to have a “take-while” implementation, and then go back to Spliterator and then to Stream. Or, perhaps, wrap Spliteratoralthough in this implementation it is no longer possible to split it.

Here is an untested implementation of takeWhile on a Spliterator:

static  Spliterator takeWhile(
    Spliterator splitr, Predicate predicate) {
  return new Spliterators.AbstractSpliterator(splitr.estimateSize(), 0) {
    boolean stillGoing = true;
    @Override public boolean tryAdvance(Consumer consumer) {
      if (stillGoing) {
        boolean hadNext = splitr.tryAdvance(elem -> {
          if (predicate.test(elem)) {
            consumer.accept(elem);
          } else {
            stillGoing = false;
          }
        });
        return hadNext && stillGoing;
      }
      return false;
    }
  };
}

static  Stream takeWhile(Stream stream, Predicate predicate) {
   return StreamSupport.stream(takeWhile(stream.spliterator(), predicate), false);
}

Leave a comment