有没有办法阻止 Stream.generate 从其 Lambda 闭包中恢复?

2022-09-05 00:22:35

我刚刚开始玩Java 8和Lambda Expression,我很好奇我是否可以通过返回特定值(如null)来阻止Lambda expession内部的Stream生成。使用 Stream.generate() 可以做到这一点吗?

private int counter;

private void generate()
{
    System.out.println(Stream.generate(() -> {
        if (counter < 10) {
            counter++;
            return RandomUtils.nextInt(100);
        } else {
            return null;
        }
    }).count());
}

不幸的是,此代码不会终止,因此通过简单地返回不会退出流。null


答案 1

Java 9 及更高版本包含此方法

Stream<T> takeWhile(Predicate<? super T> predicate); 

以按条件限制流。因此,不再需要下面的解决方法。

原始答案(适用于早于 9 的 Java 版本):

使用 Stream.generate,这是从 lambda 闭包中无法实现的每个定义。根据定义,它是无止境的。使用,您可以使流修复大小。但这对以下情况没有帮助:limit()

if random>10 then stop

有可能通过条件限制潜在的无休止流。如果不知道大小,这是有用的。你的朋友在这里是一个拆分器,你的示例代码看起来像这样:

System.out.println( StreamSupport.stream(Spliterators.spliteratorUnknownSize(new Iterator<Integer>() {
    int counter = 0;

    @Override
    public boolean hasNext() {
        return counter < 10;
    }

    @Override
    public Integer next() {
        counter++;
        return RandomUtils.nextInt(100);
    }
}, Spliterator.IMMUTABLE), false).count());

基本上,您可以从迭代构建。例如,我正在使用这个构造来表示来自Stax XML的XMLEvents流 - 解析。

我知道这不是由lambda构造完成的,但它IHMO解决了按条件停止流项目生成的这个缺乏的功能。

如果有更好的方法可以实现这一点(我的意思是这个流构造而不是XML处理;)),或者以这种方式使用流存在根本性缺陷,我会非常感兴趣。


答案 2

这在 Lamdas 中是不可能的,您无法从表达式内部控制流。甚至API文档也说Stream.generate会生成无限的流。

但是,您只需使用 limit() 方法即可限制 Stream 并实现所需的功能:

System.out.println(Stream.generate(() -> RandomUtils.nextInt(100)).limit(10).count());

推荐