一尘不染

Java 用谓词限制流

java

是否存在Java 8流操作来限制(可能是无限的)Stream直到第一个元素与谓词不匹配?

在Java 9中,我们可以使用takeWhile下面的示例来打印所有小于10的数字。

IntStream
    .iterate(1, n -> n + 1)
    .takeWhile(n -> n < 10)
    .forEach(System.out::println);

由于Java 8中没有这样的操作,以一般方式实现它的最佳方法是什么?


阅读 443

收藏
2020-02-26

共2个答案

一尘不染

操作takeWhiledropWhile已添加到JDK9。你的示例代码

IntStream
    .iterate(1, n -> n + 1)
    .takeWhile(n -> n < 10)
    .forEach(System.out::println);

在JDK 9下编译和运行时,其行为将完全符合你的预期。

JDK 9已发布。可在此处下载:http : //jdk.java.net/9/

2020-02-26
一尘不染

这样的操作在Java 8中应该是可能的Stream,但不一定有效地完成-例如,你不必并行化这样的操作,因为你必须按顺序查看元素。

该API并没有提供一种简便的方法,但是最简单的方法可能是将其Stream.iterator()打包,包装Iterator成具有“ take-while”的实现,然后返回到Spliterator然后是a Stream。或者-也许-包装Spliterator,尽管在该实现中它实际上不能再拆分了。

下面是一个未经测试的执行takeWhile上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);
}
2020-02-26