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 <T> Spliterator<T> takeWhile(
    Spliterator<T> splitr, Predicate<? super T> predicate) {
  return new Spliterators.AbstractSpliterator<T>(splitr.estimateSize(), 0) {
    boolean stillGoing = true;
    @Override public boolean tryAdvance(Consumer<? super T> consumer) {
      if (stillGoing) {
        boolean hadNext = splitr.tryAdvance(elem -> {
          if (predicate.test(elem)) {
            consumer.accept(elem);
          } else {
            stillGoing = false;
          }
        });
        return hadNext && stillGoing;
      }
      return false;
    }
  };
}

static <T> Stream<T> takeWhile(Stream<T> stream, Predicate<? super T> predicate) {
   return StreamSupport.stream(takeWhile(stream.spliterator(), predicate), false);
}

Leave a comment