Javaでのストリームと配列間の変換

1. 前書き

link:/convert-map-values-to-array-list-set[convert]さまざまなlink:/convert-array-to-list-が必要になることがよくありますand-list-to-array [動的データ構造]をlink:/convert-array-to-set-and-set-to-array[arrays]に追加します。
このチュートリアルでは、Javaでlink:/java-8-streams-introduction[_Stream_]を配列に、またはその逆に変換する方法を示します。

2. _Stream_から配列への変換

2.1. メソッドリファレンス

  • _Stream_を配列に変換する最良の方法は、 Stream ‘ s _toArray()_メソッドを使用することです*

public String[] usingMethodReference(Stream<String> stringStream) {
    return stringStream.toArray(String[]::new);
}
これで、変換が成功したかどうかを簡単にテストできます。
Stream<String> stringStream = Stream.of("baeldung", "convert", "to", "string", "array");
assertArrayEquals(new String[] { "baeldung", "convert", "to", "string", "array" },
    usingMethodReference(stringStream));

2.2. ラムダ式

別の同等の方法は、ラムダ式を_toArray_()メソッドに渡すことです:
public static String[] usingLambda(Stream<String> stringStream) {
    return stringStream.toArray(size -> new String[size]);
}
これにより、メソッド参照を使用した場合と同じ結果が得られます。

2.3. カスタムクラス

または、すべて出かけて本格的なクラスを作成することもできます。
https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#toArray-java.util.function.IntFunction-[_Stream_ documentation]からわかるように、 _IntFunction_を引数として取ります。 入力として配列サイズを取り、そのサイズの配列を返します。
もちろん、__IntFunction __はインターフェイスなので、実装できます。
class MyArrayFunction implements IntFunction<String[]> {
    @Override
    public String[] apply(int size) {
        return new String[size];
    }
};
その後、通常どおりに構築して使用できます。
public String[] usingCustomClass(Stream<String> stringStream) {
    return stringStream.toArray(new MyArrayFunction());
}
その結果、以前と同じアサーションを作成できます。

2.4. プリミティブ配列

前のセクションでは、文字列ストリームを文字列配列に変換する方法を検討しました。 実際、どのような_Object_に対してもこの方法で変換を実行でき、上記の_String_の例と非常によく似ています。
ただし、プリミティブでは少し異なります。 たとえば、__ Integer [_]に変換する__Integer__sの_Stream_がある場合、最初に_mapToInt()_メソッドを呼び出す必要があります。
public int[] intStreamToPrimitiveIntArray(Stream<Integer> integerStream) {
    return integerStream.mapToInt(i -> i).toArray();
}
また、自由に使用できる_mapToLong()_および_mapToDouble()_メソッドもあります。 また、今回は_toArray()_に引数を渡していないことに注意してください。
最後に、等価性アサーションを実行して、_int_配列が正しく設定されていることを確認します。
Stream<Integer> integerStream = IntStream.rangeClosed(1, 7).boxed();
assertArrayEquals(new int[]{1, 2, 3, 4, 5, 6, 7}, intStreamToPrimitiveIntArray(integerStream));
しかし、反対のことをする必要がある場合はどうでしょうか? 見てみましょう。

3. 配列を_Stream_に変換する

もちろん、他の方法も可能です。 また、Javaには専用のメソッドがいくつかあります。

3.1. オブジェクトの配列

  • _Arrays.stream()_または_Stream.of()_メソッドを使用して、配列を_Stream_に変換できます*:

public Stream<String> stringArrayToStreamUsingArraysStream(String[] stringArray) {
    return Arrays.stream(stringArray);
}

public Stream<String> stringArrayToStreamUsingStreamOf(String[] stringArray) {
    return Stream.of(stringArray);
}
*どちらの場合でも、_Stream_は配列と同じ時間であることに注意してください。*

3.2. プリミティブの配列

同様に、プリミティブの配列を変換できます。
public IntStream primitiveIntArrayToStreamUsingArraysStream(int[] intArray) {
    return Arrays.stream(intArray);
}

public Stream<int[]> primitiveIntArrayToStreamUsingStreamOf(int[] intArray) {
    return Stream.of(intArray);
}
ただし、__ Object__s配列の変換とは対照的に、重要な違いがあります。 *プリミティブ配列を変換すると、_Arrays.stream()_は_IntStream_を返し、_Stream.of()_は_Stream <int []> _。*を返します。

3.3. Arrays.stream vs. Stream.of

前のセクションで述べた違いを理解するために、対応するメソッドの実装を見ていきます。
最初に、これら2つのメソッドのJavaの実装を見てみましょう。
public <T> Stream<T> stream(T[] array) {
    return stream(array, 0, array.length);
}

public <T> Stream<T> of(T... values) {
    return Arrays.stream(values);
}
_Stream.of()_が実際に_Arrays.stream()_を内部で呼び出していることがわかります。これが明らかに同じ結果を得る理由です。
ここで、プリミティブの配列を変換する場合のメソッドをチェックアウトします。
public IntStream stream(int[] array) {
    return stream(array, 0, array.length);
}

public <T> Stream<T> of(T t) {
    return StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false);
}
今回は、_Stream.of()_は_Arrays.stream()_を呼び出していません。

4. 結論

この記事では、__ Stream__sをJavaで配列に変換する方法と、その逆の方法を説明しました。 また、__ Object__sの配列を変換するときとプリミティブの配列を使用するときに異なる結果が得られる理由についても説明しました。
いつものように、完全なソースコードはhttps://github.com/eugenp/tutorials/tree/master/core-java-modules/core-java-arrays-2[GitHubで]にあります。