如何创建无限流< E>超出迭代器< E>? [英] How to create an infinite Stream<E> out of an Iterator<E>?

查看:121
本文介绍了如何创建无限流< E>超出迭代器< E>?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

查看以下课程:

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

我如何创建无限 流< E>

如果我使用 Stream< ;整数> infiniteStream = toList(FibonacciSupplier.infinite())。stream(),我可能会惊讶地发现,永远不会得到无限的流。

相反,代码会永远循环创建基础方法中的列表

If I were to use Stream<Integer> infiniteStream = toList(FibonacciSupplier.infinite()).stream(), I would, possibly surprisingly, never get an infinite stream.
Instead the code would loop forever in the creation of the list in an underlying method.

到目前为止,这纯粹是理论上的,但我可以肯定地了解需要因为如果我想首先从无限流中跳过前x个数字,然后用最后的y数限制它,例如:

This so far is purely theoretical, but I can definately understand the need for it if I would want to first skip the first x numbers from an infinite stream, and then limit it by the last y numbers, something like:

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

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

The code would not ever return a result, how should it be done?

推荐答案

你的错误是认为你需要 Iterator 收集以创建。为了创建无限流,提供一个又一个值的单个方法就足够了。所以对于你的班级 FibonacciSupplier 最简单的用法是:

Your mistake is to think that you need an Iterator or a Collection to create a Stream. For creating an infinite stream, a single method providing one value after another is enough. So for your class FibonacciSupplier the simplest use is:

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

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

or, if you prefer boxed values:

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

请注意,在这种情况下,该方法不必命名为 next 也不满足 Iterator 界面。但是,如果它和你的班级一样没关系。此外,正如我们刚刚告诉流使用 next 方法作为供应商将永远不会调用hasNext 方法。它只是无限的。

Note that in this case the method does not have to be named next nor fulfill the Iterator interface. But it doesn’t matter if it does as with your class. Further, as we just told the stream to use the next method as a Supplier, the hasNext method will never be called. It’s just infinite.

使用 Iterator 创建有限流有点复杂:

Creating a finite stream using your Iterator is a bit more complicated:

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

在这种情况下,如果你想要一个有限的 IntStream 使用未装箱的 int FibonacciSupplier 应实现 PrimitiveIterator.OfInt

In this case if you want a finite IntStream with unboxed int values your FibonacciSupplier should implement PrimitiveIterator.OfInt.

这篇关于如何创建无限流&lt; E&gt;超出迭代器&lt; E&gt;?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆