1概要

このクイック記事では、Javaの

Streams

をマージするさまざまな方法について説明します。これは非常に直感的な操作ではありません。


2プレーンJava

の使い方

JDK 8の

Stream

クラスには、便利な静的ユーティリティメソッドがいくつかあります。

concat()

メソッドを詳しく見てみましょう。


2.1. 2つの

Streams


を結合する

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. 複数の

__Stream

__s

をマージする

2つ以上の

Streamをマージする必要があるとき、

物事はもう少し複雑になります。 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つの

    Streamsを含む新しい

    Stream__を作成します。


Stream <Stream <Integer>>

になります。
** それから、

flatMap()

アイデンティティーを使用して

Stream <Integer>

にこれを__します。

関数


3 StreamEx

を使用する


StreamEx

は、Java 8 Streamsの可能性を広げるオープンソースのJavaライブラリです。 JDKの

Stream

インタフェースの拡張として、

StreamEx

クラスが使用されています。


3.1.

__Stream

__s

をマージする

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には、

prepend()

という名前の要素を順番に追加するメソッドも含まれています。

@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に便利な拡張機能を提供するJDK 8互換のライブラリです。ここで最も重要なストリームの抽象化は

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λには

prepend()

メソッドもあります。

@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で利用可能

のソースコードを見つけることができます。