问题描述
看看我制作的以下课程:
Looking at the following class I've made:
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;
}
}
我怎样才能创建一个infinite Stream<E>
?
How would I be able to create an infinite Stream<E>
?
如果我使用 Stream<Integer>infiniteStream = toList(FibonacciSupplier.infinite()).stream()
,可能令人惊讶的是,我永远不会得到无限流.
相反,代码将在底层方法中创建 list
时永远循环.
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
或一个 Collection
来创建一个 流
.对于创建无限流,一个方法提供一个接一个的值就足够了.所以对于你的类 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
方法作为 Supplier
,因此永远不会调用 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);
在这种情况下,如果您想要一个具有未装箱 int
值的有限 IntStream
,您的 FibonacciSupplier
应该实现 PrimitiveIterator.OfInt
.
In this case if you want a finite IntStream
with unboxed int
values your FibonacciSupplier
should implement PrimitiveIterator.OfInt
.
这篇关于如何创建无限流<E>出迭代器<E>?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!