Javaでのストリームのマージ
1. 概要
この簡単な記事では、JavaStreamsをマージするさまざまな方法について説明します。これはあまり直感的な操作ではありません。
2. プレーンJavaの使用
JDK 8Streamクラスには、いくつかの便利な静的ユーティリティメソッドがあります。 concat()メソッドを詳しく見てみましょう。
2.1. 2つのStreamsをマージする
2Streamsを組み合わせる最も簡単な方法は、静的なStream.concat()メソッドを使用することです。
@Test
public void whenMergingStreams_thenResultStreamContainsElementsFromBoth() {
Stream stream1 = Stream.of(1, 3, 5);
Stream stream2 = Stream.of(2, 4, 6);
Stream resultingStream = Stream.concat(stream1, stream2);
assertEquals(
Arrays.asList(1, 3, 5, 2, 4, 6),
resultingStream.collect(Collectors.toList()));
}
2.2. 複数のStreamsをマージする
2Streams,を超えてマージする必要がある場合、状況は少し複雑になります。 1つの可能性は、最初の2つのストリームを連結してから、次のストリームと結果を連結することです。
次のコードスニペットは、これを実際に示しています。
@Test
public void given3Streams_whenMerged_thenResultStreamContainsAllElements() {
Stream stream1 = Stream.of(1, 3, 5);
Stream stream2 = Stream.of(2, 4, 6);
Stream stream3 = Stream.of(18, 15, 36);
Stream resultingStream = Stream.concat(
Stream.concat(stream1, stream2), stream3);
assertEquals(
Arrays.asList(1, 3, 5, 2, 4, 6, 18, 15, 36),
resultingStream.collect(Collectors.toList()));
}
ご覧のとおり、このアプローチはより多くのストリームに対して実行不可能になります。 もちろん、中間変数またはヘルパーメソッドを作成して読みやすくすることもできますが、ここではより良いオプションを示します。
@Test
public void given4Streams_whenMerged_thenResultStreamContainsAllElements() {
Stream stream1 = Stream.of(1, 3, 5);
Stream stream2 = Stream.of(2, 4, 6);
Stream stream3 = Stream.of(18, 15, 36);
Stream stream4 = Stream.of(99);
Stream resultingStream = Stream.of(
stream1, stream2, stream3, stream4)
.flatMap(i -> i);
assertEquals(
Arrays.asList(1, 3, 5, 2, 4, 6, 18, 15, 36, 99),
resultingStream.collect(Collectors.toList()));
}
ここで何が起こるかです:
-
最初に、4つのStreams,を含む新しいStreamを作成します。これにより、Stream<Stream<Integer>>が生成されます。
-
次に、恒等関数を使用して、これをStream<Integer>にflatMap()します。
3. StreamExの使用
StreamExは、Java8ストリームの可能性を拡張するオープンソースのJavaライブラリです。 JDKのStreamインターフェースの拡張機能としてStreamExクラスを使用します。
3.1. Streamsのマージ
StreamExライブラリを使用すると、append()インスタンスメソッドを使用してストリームをマージできます。
@Test
public void given4Streams_whenMerged_thenResultStreamContainsAllElements() {
Stream stream1 = Stream.of(1, 3, 5);
Stream stream2 = Stream.of(2, 4, 6);
Stream stream3 = Stream.of(18, 15, 36);
Stream stream4 = Stream.of(99);
Stream resultingStream = StreamEx.of(stream1)
.append(stream2)
.append(stream3)
.append(stream4);
assertEquals(
Arrays.asList(1, 3, 5, 2, 4, 6, 18, 15, 36, 99),
resultingStream.collect(Collectors.toList()));
}
これはインスタンスメソッドであるため、簡単にチェーン化して複数のストリームを追加できます。
resultingStream変数をStreamExタイプに入力すると、toList()を使用してストリームからListを作成することもできることに注意してください。
3.2. prepend()を使用したストリームのマージ
StreamExには、prepend()と呼ばれる要素を相互に追加するメソッドも含まれています。
@Test
public void given3Streams_whenPrepended_thenResultStreamContainsAllElements() {
Stream stream1 = Stream.of("foo", "bar");
Stream openingBracketStream = Stream.of("[");
Stream closingBracketStream = Stream.of("]");
Stream resultingStream = StreamEx.of(stream1)
.append(closingBracketStream)
.prepend(openingBracketStream);
assertEquals(
Arrays.asList("[", "foo", "bar", "]"),
resultingStream.collect(Collectors.toList()));
}
4. Jooλの使用
jOOλは、JDKに便利な拡張機能を提供するJDK8互換ライブラリです。 ここで最も重要なストリームの抽象化はSeqと呼ばれます。 これはシーケンシャルで順序付けられたストリームであるため、parallel()を呼び出しても効果がないことに注意してください。
4.1. ストリームのマージ
StreamExライブラリと同様に、jOOλにはappend()メソッドがあります。
@Test
public void given2Streams_whenMerged_thenResultStreamContainsAllElements() {
Stream seq1 = Stream.of(1, 3, 5);
Stream seq2 = Stream.of(2, 4, 6);
Stream resultingSeq = Seq.ofType(seq1, Integer.class)
.append(seq2);
assertEquals(
Arrays.asList(1, 3, 5, 2, 4, 6),
resultingSeq.collect(Collectors.toList()));
}
また、resultingSeq変数をjOOλSeq型に入力すると、便利なtoList()メソッドがあります。
4.2. ストリームとprepend()のマージ
予想どおり、append()メソッドが存在するため、jOOλにはprepend()メソッドもあります。
@Test
public void given3Streams_whenPrepending_thenResultStreamContainsAllElements() {
Stream seq = Stream.of("foo", "bar");
Stream openingBracketSeq = Stream.of("[");
Stream closingBracketSeq = Stream.of("]");
Stream resultingStream = Seq.ofType(seq, String.class)
.append(closingBracketSeq)
.prepend(openingBracketSeq);
Assert.assertEquals(
Arrays.asList("[", "foo", "bar", "]"),
resultingStream.collect(Collectors.toList()));
}
5. 結論
JDK 8を使用すると、ストリームのマージが比較的簡単であることがわかりました。 多くのマージを行う必要がある場合、読みやすくするためにStreamExまたはjOOλライブラリを使用すると有益な場合があります。
ソースコードover on GitHubを見つけることができます。