Limit a stream by a predicate

前端 未结 19 3133
别跟我提以往
别跟我提以往 2020-11-21 22:54

Is there a Java 8 stream operation that limits a (potentially infinite) Stream until the first element fails to match a predicate?

In Java 9 we can use

19条回答
  •  后悔当初
    2020-11-21 23:55

    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  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);
    }
    

提交回复
热议问题