これを行うには正しい方法ではありませんが、自分でSpliterator
を書きます。一般的なアルゴリズムは以下の通りです:
- は、いくつかの追加の操作を行って、おそらく進める際に、既存のものの要素を消費する可能性がある独自のSpliteratorを書く
stream.spliterator()
- を使用して、既存のストリームSpliteratorしてください。
.onClose(stream::close)
のような元のストリームにStreamSupport.stream(spliterator, stream.isParallel())
- 委任
close()
呼び出しを介して、あなたのspliteratorに基づいて新しいストリームを作成します。
よく平行化する優れたスプライテータを書くことは、しばしば非常に重要ではありません。しかし、並列化を気にしなければ、より簡単なサブクラスAbstractSpliterator
を作成することができます。ここで指定した位置にある要素を削除し、新たなストリーム操作を作成する方法の例です:
public static <T> Stream<T> removeAt(Stream<T> src, int idx) {
Spliterator<T> spltr = src.spliterator();
Spliterator<T> res = new AbstractSpliterator<T>(Math.max(0, spltr.estimateSize()-1),
spltr.characteristics()) {
long cnt = 0;
@Override
public boolean tryAdvance(Consumer<? super T> action) {
if(cnt++ == idx && !spltr.tryAdvance(x -> {}))
return false;
return spltr.tryAdvance(action);
}
};
return StreamSupport.stream(res, src.isParallel()).onClose(src::close);
}
これは、最小限の実装であり、より良いパフォーマンスと並列性を示すように改善することができます。
私のStreamExライブラリでは、headTail
を介してこのようなカスタムストリーム操作の追加を簡素化しようとしました。ここでStreamEx
を使用して同じことをする方法は次のとおりです。
public static <T> StreamEx<T> removeAt(StreamEx<T> src, int idx) {
// head is the first stream element
// tail is the stream of the rest elements
// want to remove first element? ok, just remove tail
// otherwise call itself with decremented idx and prepend the head element to the result
return src.headTail(
(head, tail) -> idx == 0 ? tail : removeAt(tail, idx-1).prepend(head));
}
あなたもchain()
方法で連鎖をサポートすることができます:
public static <T> Function<StreamEx<T>, StreamEx<T>> removeAt(int idx) {
return s -> removeAt(s, idx);
}
使用例:
StreamEx.of("Java 8", "Stream", "API", "is", "not", "great")
.chain(removeAt(4)).forEach(System.out::println);
が最後にさえなしheadTail
があることに注意してくださいStreamExを使用して問題を解決するいくつかの方法。あなたが増えてジッパーがあり、特定のインデックスに削除するには、このようにインデックスをフィルタリングし、ドロップ:
StreamEx.of(stream)
.zipWith(IntStreamEx.ints().boxed())
.removeValues(pos -> pos == idx)
.keys();
がcollapse
方法を捧げていますが、隣接する繰り返しを折りたたむには(それも非常によく並列化!):
StreamEx.of(stream).collapse(Object::equals);
あなたの例でストリーミングされませコレクションを持つことが必要です。ここでは
が変更されたコードです、再度隣接する複製は不可能です。私はあなたがどうにかして、例えば、 7番目の要素のみ。 –
まあ、 'distinct'はどういうわけか隣接する重複を削除するので、明らかに可能です。しかし、最後の要素を削除することが適切に定義されていない可能性があることに同意します。 – piotrek
'distinct'は単純なアルゴリズムで、Linuxのuniqコマンドと同じように動作します。あなたがする必要があるのは、以前見た価値を把握することだけです。現在の値が異なる場合は、前の値として記録します。同じ場合は、この要素をスキップして続けます。多くの場合、あなたはいつでも2つの連続した要素を見ています。あなたの要件は 'Stream'についての仮定を真実ではないかもしれないし、あなたが' Stream'を処理するまで見つけることができません。 – nickb