2016-08-18 5 views
19

Java 8で要素をグループ化する方法はありませんか?java.util.stream.Streamを収集することはありませんか?結果をStreamに戻してください。私は多くのデータや無限のストリームで作業しなければならないので、まずデータを収集して結果を再びストリーミングすることはできません。Java8ストリームを収集せずにグルーピングする

グループ化する必要があるすべての要素は、最初のストリームで連続しています。したがって、私はストリーム評価を怠惰に保つのが好きです。

+2

データがすでに「グループ化されている」(連続している)場合、グループ化されたフォームでそのデータが必要なのはなぜですか?いくつかの文脈を提供することで、この質問に対するより良い答えが得られるかもしれません。 –

+0

収集せずに 'Collectors'から' groupBy'を使うことを意味しますか? – ByeBye

+1

キューのジョブのように聞こえ、ストリームではありません。キューから連続した要素を消費して、次のグループがある場合は先頭を検出し、そのグループを含む次のキューにグループを追加します。 – Hulk

答えて

19

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

ただし、グループ化するアイテムが入力ストリームに常に隣接していることがわかっている場合は、ストリーム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))は、各リストに同じ文字で始まる隣接する文字列が含まれる文字列のリストのストリームを作成します。

他の部分的な縮小操作には、intervalMap,runLengths()などが含まれます。

すべての部分的縮小操作は、遅延があり、並列に優しく、非常に効率的です。

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

+0

あなたのライブラリーをチェックアウトします。これはまさに私が必要としているようです。提案していただきありがとうございます。 –

+2

うーん、興味深い。これはOPsの実際のコードに適用されて見て非常にいいですか、@MatthiasWimmer –

関連する問題