当前位置: 首页 > 知识库问答 >
问题:

如何从迭代器中创建无限流?

狄冠宇
2023-03-14

看看我制作的以下类:

public class FibonacciSupplier implements Iterator<Integer> {
    private final IntPredicate hasNextPredicate;

    private int beforePrevious = 0;
    private int previous = 1;

    private FibonacciSupplier(final IntPredicate hasNextPredicate) {
        this.hasNextPredicate = hasNextPredicate;
    }

    @Override
    public boolean hasNext() {
        return hasNextPredicate.test(previous);
    }

    @Override
    public Integer next() {
        int result = beforePrevious + previous;
        beforePrevious = previous;
        previous = result;
        return result;
    }

    public static FibonacciSupplier infinite() {
        return new FibonacciSupplier(i -> true);
    }

    public static FibonacciSupplier finite(final IntPredicate predicate) {
        return new FibonacciSupplier(predicate);
    }
} 

以及它在以下方面的用法:

public class Problem2 extends Problem<Integer> {
    @Override
    public void run() {
        result = toList(FibonacciSupplier.finite(i -> (i <= 4_000_000)))
                .stream()
                .filter(i -> (i % 2 == 0))
                .mapToInt(i -> i)
                .sum();
    }

    @Override
    public String getName() {
        return "Problem 2";
    }

    private static <E> List<E> toList(final Iterator<E> iterator) {
        List<E> list = new ArrayList<>();
        while (iterator.hasNext()) {
            list.add(iterator.next());
        }
        return list;
    }
}

如果我使用stream infiniteStream=toList(FibonAccisupplier.infinite()).stream() ,可能令人惊讶的是,我将永远得不到无限流
相反,代码将在底层方法中创建list时永远循环。

到目前为止,这是纯理论上的,但如果我想首先跳过无限流中的前x个数字,然后用最后的y个数字来限制它,我可以明确地理解它的必要性,如下所示:

int x = MAGIC_NUMBER_X;
int y = MAGIC_NUMBER_y;
int sum = toList(FibonacciSupplier.infinite())
    .stream()
    .skip(x)
    .limit(y)
    .mapToInt(i -> i)
    .sum();

代码不会返回一个结果,应该怎么做呢?

共有1个答案

公羊俊德
2023-03-14

您的错误是认为需要迭代器集合来创建。对于创建无限流,提供一个又一个值的单个方法就足够了。因此,对于您的类FibonAccisupplier来说,最简单的用法是:

IntStream s=IntStream.generate(FibonacciSupplier.infinite()::next);

或者,如果您更喜欢装箱的值:

Stream<Integer> s=Stream.generate(FibonacciSupplier.infinite()::next);

注意,在这种情况下,方法不必命名为next,也不必实现iterator接口。但这和你的班级一样无关紧要。此外,由于我们刚刚告诉流使用next方法作为供应商,因此将永远不会调用hasnext方法。只是无限。

Stream<Integer> s=StreamSupport.stream(
  Spliterators.spliteratorUnknownSize(
    FibonacciSupplier.finite(intPredicate), Spliterator.ORDERED),
  false);

在这种情况下,如果希望使用未装箱的IntStream值的有限IntStream,您的FibonAccisupplier应该实现PrimitiveIterator.oFint

 类似资料:
  • 是否可以从迭代器创建一个流,其中对象的序列与通过反复调用迭代器的next()方法生成的序列相同?我所考虑的具体情况涉及到Treeset.desceningIterator()返回的迭代器的使用,但是我可以想象在其他情况下,迭代器是可用的,而不是它所引用的集合。 例如,对于,我们可以编写并按照该集合的排序顺序获取该集合中的对象流,但是如果我们希望它们按照不同的顺序,比如通过使用获得的顺序呢?我想象的

  • 问题内容: 是否可以从迭代器创建一个Stream,其中对象的序列与通过重复调用迭代器的next()方法生成的对象的序列相同?我正在考虑的特定情况涉及TreeSet.descendingIterator()返回的迭代器的使用,但是我可以想象在其他情况下可以使用迭代器而不是它引用的集合。 例如,对于a,我们可以按照集合的排序顺序来编写并获取该集合中的对象流,但是如果我们希望它们以不同的顺序(例如,使用

  • 问题内容: 我创建了一个函数,该函数生成连续递增的字母列表。A,B,C …,Z。在Z之后,到达AA,AB,AC … AZ。此模式重复。这类似于MS Excel的列名。目前,此函数会生成一个有限的字母列表。 然后,我可以结合一些有限列表(例如0-10)对其进行迭代。请参阅下面的代码。我想要的是创建一个生成器,该生成器将为我提供无限长的递增字母列表。 问题答案: 每次都产生Yield的最后一个元素,并

  • 我天真地试图这样做: 要创建迭代器,我可以使用闭包轻松地发送到任务。 但是,它会产生可怕的寿命不匹配错误: 我不明白这个错误。 闭包应采用生命周期为“a”的参数,即结构的生命周期。 国家为结构所有,因此其生命周期为“a”。 使用下一步。召唤(( 所以这里的不匹配是下一个()中的自我终生和“呼叫中的a”之间的不匹配...但我不明白为什么它不是“a”。 修复上述代码的正确方法是什么? 有没有更好的方法

  • 问题 你在代码中使用 while 循环来迭代处理数据,因为它需要调用某个函数或者和一般迭代模式不同的测试条件。 能不能用迭代器来重写这个循环呢? 解决方案 一个常见的IO操作程序可能会想下面这样: CHUNKSIZE = 8192 def reader(s): while True: data = s.recv(CHUNKSIZE) if data ==

  • 问题内容: 此代码将导致无限循环的机会是什么? 实际上,这会导致无限循环。我的怀疑是因为我没有服用,是真的吗? 问题答案: 是。除非您不打电话,否则它将永远不会继续进行下一项。Beause 将返回您已在列表/集中添加的对象。