是否有Java 8流操作限制流(可能是无限的),直到第一个元素无法匹配谓词?
在Java 9中,我们可以像下面的例子一样使用takeWhile来打印所有小于10的数字。
IntStream
.iterate(1, n -> n + 1)
.takeWhile(n -> n < 10)
.forEach(System.out::println);
因为在Java 8中没有这样的操作,那么以通用的方式实现它的最佳方法是什么呢?
是否有Java 8流操作限制流(可能是无限的),直到第一个元素无法匹配谓词?
在Java 9中,我们可以像下面的例子一样使用takeWhile来打印所有小于10的数字。
IntStream
.iterate(1, n -> n + 1)
.takeWhile(n -> n < 10)
.forEach(System.out::println);
因为在Java 8中没有这样的操作,那么以通用的方式实现它的最佳方法是什么呢?
当前回答
除非通过短路终端操作,否则不能中止流,这将使一些流值无论其值如何都未得到处理。但是如果你只是想避免流上的操作,你可以添加一个转换和过滤器到流:
import java.util.Objects;
class ThingProcessor
{
static Thing returnNullOnCondition(Thing thing)
{ return( (*** is condition met ***)? null : thing); }
void processThings(Collection<Thing> thingsCollection)
{
thingsCollection.stream()
*** regular stream processing ***
.map(ThingProcessor::returnNullOnCondition)
.filter(Objects::nonNull)
*** continue stream processing ***
}
} // class ThingProcessor
它会在满足某些条件时将数据流转换为null,然后过滤掉null。如果您愿意考虑副作用,可以在遇到某些事情时将条件值设置为true,这样所有后续事情都会被过滤掉,而不管它们的值是多少。但即使不是这样,您也可以通过从流中过滤不想处理的值来节省大量(如果不是全部)处理。
其他回答
takeWhile是质子包库提供的函数之一。
Stream<Integer> infiniteInts = Stream.iterate(0, i -> i + 1);
Stream<Integer> finiteInts = StreamUtils.takeWhile(infiniteInts, i -> i < 10);
assertThat(finiteInts.collect(Collectors.toList()),
hasSize(10));
下面是我使用Java流库的尝试。
IntStream.iterate(0, i -> i + 1)
.filter(n -> {
if (n < 10) {
System.out.println(n);
return false;
} else {
return true;
}
})
.findAny();
IntStream.iterate(1, n -> n + 1)
.peek(System.out::println) //it will be executed 9 times
.filter(n->n>=9)
.findAny();
您可以使用mapToObj来返回最终对象或消息,而不是peak
IntStream.iterate(1, n -> n + 1)
.mapToObj(n->{ //it will be executed 9 times
if(n<9)
return "";
return "Loop repeats " + n + " times";});
.filter(message->!message.isEmpty())
.findAny()
.ifPresent(System.out::println);
实际上,在Java 8中有两种方法可以做到这一点,不需要任何额外的库或使用Java 9。
如果你想在控制台上打印2到20的数字,你可以这样做:
IntStream.iterate(2, (i) -> i + 2).peek(System.out::println).allMatch(i -> i < 20);
or
IntStream.iterate(2, (i) -> i + 2).peek(System.out::println).anyMatch(i -> i >= 20);
两种情况下的输出都是:
2
4
6
8
10
12
14
16
18
20
还没有人提到match。这就是我写这篇文章的原因。
操作takeWhile和dropWhile已添加到JDK 9中。示例代码
IntStream
.iterate(1, n -> n + 1)
.takeWhile(n -> n < 10)
.forEach(System.out::println);
在JDK 9下编译和运行时,它的行为将完全符合您的预期。
JDK 9已经发布。可以在这里下载:JDK 9发行版。