web-dev-qa-db-ja.com

収集せずにJava8ストリームをグループ化する

Java 8で、要素を収集せずにJava.util.stream.Streamの要素をグループ化する方法はありますか?結果を再びStreamにしたいのです。大量のデータや無限のストリームを扱う場合、最初にデータを収集して結果を再度ストリーミングすることはできません。

グループ化する必要があるすべての要素は、最初のストリームで連続しています。したがって、私はストリーム評価を遅延させておくのが好きです。

32
Matthias Wimmer

標準のストリームAPIを使用してそれを行う方法はありません。一般に、作成済みのグループのいずれかに属する新しいアイテムが将来表示される可能性があるため、すべての入力を処理するまでグループをダウンストリーム分析に渡すことはできないため、これを行うことはできません。

ただし、グループ化する項目が入力ストリーム内で常に隣接していることが事前にわかっている場合は、Stream APIを拡張するサードパーティライブラリを使用して問題を解決できます。そのようなライブラリの1つは StreamEx であり、これは無料で私が作成したものです。これには、いくつかの述語に基づいて隣接するアイテムを単一に折りたたむ「部分削減」演算子がいくつか含まれています。通常、2つの隣接するアイテムをテストし、それらをグループ化する必要がある場合はtrueを返すBiPredicateを指定する必要があります。部分削減操作の一部を以下に示します。

  • collapse(BiPredicate) :各グループをグループの最初の要素で置き換えます。たとえば、collapse(Objects::equals)は、ストリームから隣接する重複を削除するのに役立ちます。
  • groupRuns(BiPredicate) :各グループをグループ要素のリストで置き換えます(つまり、_StreamEx<T>_は_StreamEx<List<T>>_に変換されます)。たとえば、stringStream.groupRuns((a, b) -> a.charAt(0) == b.charAt(0))は、文字列のリストのストリームを作成します。各リストには、同じ文字で始まる隣接する文字列が含まれます。

その他の部分的な縮小操作には、 intervalMaprunLengths() などがあります。

すべての部分削減操作は、遅延、並列処理、および非常に効率的です。

StreamEx.of(stream)を使用して、通常のJava 8ストリームからStreamExオブジェクトを簡単に作成できます。また、配列、コレクション、リーダーから作成するメソッドもあります。など。StreamExクラスはStreamインターフェイスを実装し、標準のStream APIと100%互換性があります。

28
Tagir Valeev