有限ストリームは、Stream.generate
で作成されません。
ストリームを実装する標準的な方法は、Spliterator
を実装することです。the Iterator
detourを使用することもあります。どちらの場合でも、実装には終了を報告する方法があります。 Spliterator.tryAdvance
がfalse
、またはそのforEachRemaining
メソッドが返されたとき、またはIterator
のソースの場合、hasNext()
がfalse
を返したとき。
Spliterator
は、処理が開始される前に予想される要素の数を報告する場合もあります。 Stream.generate
がSpliterator
同様またはストリーム実装の内部機能を使用して、どちらか実装されてもよいが、関係なく、それらが実装されているかの、あなたは「ドンのようなStream
インターフェース内の工場のいずれかの方法で作成された
ストリーム、そのようなストリームを有限にする唯一の方法は、limit
操作をストリームに連結することです。
配列またはコレクションの背後にない空でない空のストリームを作成し、既存のストリームソースのいずれも適合しない場合は、独自のSpliterator
およびcreate a stream out of itを実装する必要があります。上記のように、既存の方法を使用してIterator
からSpliterator
を作成することはできますが、慣れているという理由でIterator
を使用する誘惑に抵抗する必要があります。あなたは、例えばdefault
Spliterator
インタフェース、重み付け開発費の方法と潜在的なパフォーマンスの向上、の上書きを追加することができ、この出発点から
/** like {@code Stream.generate}, but with an intrinsic limit */
static <T> Stream<T> generate(Supplier<T> s, long count) {
return StreamSupport.stream(
new Spliterators.AbstractSpliterator<T>(count, Spliterator.SIZED) {
long remaining=count;
public boolean tryAdvance(Consumer<? super T> action) {
if(remaining<=0) return false;
remaining--;
action.accept(s.get());
return true;
}
}, false);
}
:Spliterator
は、実装することは難しいことではありません
static <T> Stream<T> generate(Supplier<T> s, long count) {
return StreamSupport.stream(
new Spliterators.AbstractSpliterator<T>(count, Spliterator.SIZED) {
long remaining=count;
public boolean tryAdvance(Consumer<? super T> action) {
if(remaining<=0) return false;
remaining--;
action.accept(s.get());
return true;
}
/** May improve the performance of most non-short-circuiting operations */
@Override
public void forEachRemaining(Consumer<? super T> action) {
long toGo=remaining;
remaining=0;
for(; toGo>0; toGo--) action.accept(s.get());
}
}, false);
}
なぜspliteratorを定義するためにイテレータを使用しないように?私はBufferedReader.lines()がこのアプローチを使用して有限ストリームを作成することを見てきました。 – Juru
'BufferedReader.lines()'は良い例です。 'next()'と '' hasNext() 'の実装を見てください(http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8-b132/java/io /BufferedReader.java?av = f#566)と、呼び出し間の状態をどのように保つ必要があるのかを示します。対照的に、スプライテータは単純なものですが、単一のメソッドが必要です: 'tryAdvance(Consumer <?super String> c){String line = readLine(); if(line == null)falseを返します。 c.accept(line);真を返します。 } 'それはそれです。実装が簡単で(例外処理を追加し、コードサイズの半分を追加する)、ラッパーは必要ありません。 – Holger
この実装はスレッドセーフですか?それは必要ですか? – WillD