問題描述
看看我制作的以下課程:
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>?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!