MForster MForster - 1 year ago 89
Java Question

Limit a stream by a predicate

Is there a Java 8 stream operation that limits a (potentially infinite)

until the first element that fails to match a predicate? Something that looks like the (non-existent)
operation in the example below and would print all numbers less than 10?

.iterate(1, n -> n + 1)
.takeWhile(n -> n < 10)

If there is no such operation, what's the best way of implementing it in a general way?

Answer Source

Such an operation ought to be possible with a Java 8 Stream, but it can't necessarily be done efficiently -- for example, you can't necessarily parallelize such an operation, as you have to look at elements in order.

The API doesn't provide an easy way to do it, but what's probably the simplest way is to take Stream.iterator(), wrap the Iterator to have a "take-while" implementation, and then go back to a Spliterator and then a Stream. Or -- maybe -- wrap the Spliterator, though it can't really be split anymore in this implementation.

Here's 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)) {
          } else {
            stillGoing = false;
        return hadNext && stillGoing;
      return false;

static <T> Stream<T> takeWhile(Stream<T> stream, Predicate<? super T> predicate) {
   return, predicate), false);
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download