Javaでのストリームのマージ
1. 概要
この簡単な記事では、Java Streamsをマージするさまざまな方法について説明します。これはあまり直感的な操作ではありません。
2. プレーンJavaの使用
JDK 8 Stream クラスには、いくつかの便利な静的ユーティリティメソッドがあります。 concat()メソッドを詳しく見てみましょう。
2.1. 2つのストリームのマージ
2つのStreamを組み合わせる最も簡単な方法は、静的 Stream.concat()メソッドを使用することです。
@Test
public void whenMergingStreams_thenResultStreamContainsElementsFromBoth() {
Stream<Integer> stream1 = Stream.of(1, 3, 5);
Stream<Integer> stream2 = Stream.of(2, 4, 6);
Stream<Integer> resultingStream = Stream.concat(stream1, stream2);
assertEquals(
Arrays.asList(1, 3, 5, 2, 4, 6),
resultingStream.collect(Collectors.toList()));
}
2.2. 複数のストリームのマージ
2つ以上のストリームをマージする必要がある場合、はもう少し複雑になります。 1つの可能性は、最初の2つのストリームを連結し、次に結果を次のストリームと連結することです。
次のコードスニペットは、これが実際に動作していることを示しています。
@Test
public void given3Streams_whenMerged_thenResultStreamContainsAllElements() {
Stream<Integer> stream1 = Stream.of(1, 3, 5);
Stream<Integer> stream2 = Stream.of(2, 4, 6);
Stream<Integer> stream3 = Stream.of(18, 15, 36);
Stream<Integer> 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<Integer> stream1 = Stream.of(1, 3, 5);
Stream<Integer> stream2 = Stream.of(2, 4, 6);
Stream<Integer> stream3 = Stream.of(18, 15, 36);
Stream<Integer> stream4 = Stream.of(99);
Stream<Integer> 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を含むストリーム、 その結果、 ストリーム
>> - 次に、 flatMap() これをストリーム
恒等関数を使用する
3. StreamExの使用
StreamEx は、Java8ストリームの可能性を拡張するオープンソースのJavaライブラリです。 これは、JDKのStreamインターフェースの拡張としてStreamExクラスを使用します。
3.1. ストリームのマージ
StreamExライブラリを使用すると、 append()インスタンスメソッドを使用してストリームをマージできます。
@Test
public void given4Streams_whenMerged_thenResultStreamContainsAllElements() {
Stream<Integer> stream1 = Stream.of(1, 3, 5);
Stream<Integer> stream2 = Stream.of(2, 4, 6);
Stream<Integer> stream3 = Stream.of(18, 15, 36);
Stream<Integer> stream4 = Stream.of(99);
Stream<Integer> 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には、 prepare()と呼ばれる要素を相互に追加するメソッドも含まれています。
@Test
public void given3Streams_whenPrepended_thenResultStreamContainsAllElements() {
Stream<String> stream1 = Stream.of("foo", "bar");
Stream<String> openingBracketStream = Stream.of("[");
Stream<String> closingBracketStream = Stream.of("]");
Stream<String> 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<Integer> seq1 = Stream.of(1, 3, 5);
Stream<Integer> seq2 = Stream.of(2, 4, 6);
Stream<Integer> 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λには prepare()メソッドもあります。
@Test
public void given3Streams_whenPrepending_thenResultStreamContainsAllElements() {
Stream<String> seq = Stream.of("foo", "bar");
Stream<String> openingBracketSeq = Stream.of("[");
Stream<String> closingBracketSeq = Stream.of("]");
Stream<String> 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λライブラリを使用すると便利な場合があります。
ソースコードはGitHubにあります。