web-dev-qa-db-ja.com

javaの2次元配列からのストリーム

N次元のIntStream配列からintを取得しようとしています。それを行うための素晴らしいAPI方法はありますか? 2つのストリームの連結方法を知っています。

26
SurenNihalani

行優先のアプローチで配列の配列を順番に処理したいと仮定すると、これはうまくいくはずです:

_int[][] arr = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };
IntStream stream = Arrays.stream(arr).flatMapToInt(x -> Arrays.stream(x));
_

最初に Arrays.stream(T[]) メソッドを呼び出します。ここで、Tは_int[]_として推論され、_Stream<int[]>_を取得し、次に Stream#flatMapToInt() メソッドは Arrays.stream(int[]) メソッドを使用して、各_int[]_要素をIntStreamにマップします。

44
Rohit Jain

Rohitの答えをさらに拡張するには、メソッド参照を使用して、必要なコードの量をわずかに短くすることができます。

int[][] arr = { {1, 2, 3}, 
                {4, 5, 6},
                {7, 8, 9} };

IntStream stream = Arrays.stream(arr).flatMapToInt(Arrays::stream);
6
Jacob G.

以前の回答に加えて、メソッド_Arrays::stream_は順次ストリームを返します( Oracle Javadoc を参照)。状況によっては、並列ストリームによってパフォーマンスが向上する場合があります。並列ストリームを明示的に要求するには、最初に_Arrays::asList_を介してリストに変換してから、結果のリストに対してparallelStream()を呼び出す必要があります。

intを使用して2次元のIntStream配列の合計を計算するには、次のコードを使用できます。

_int[][] twoDimArray = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };
IntStream intStream = Arrays.asList(twoDimArray)
    .parallelStream()               // "rows" in parallel
    .flatMapToInt(Arrays::stream);  // "columns" sequentially
int sum = intStream.sum();          // = 45
_

外側のレイヤー(行、最初の次元)を処理するために作成されたストリームは、並行して実行されますが、内側のレイヤー(列、2番目の次元)のストリームは(上記の_Arrays::stream_を使用して)順次です。

配列のサイズと構造に応じて、4倍のパフォーマンス向上が見られる場合があります(これは私が自分のテストで測定したものです)。計算が時間的に重要な場合は、並列ストリームを使用することをお勧めします。

1
fiftyone_51

要素のみを処理するには、Rohitの回答のようにflatMapを使用します。

インデックス付きの要素を処理するには、 IntStream.range 以下のようになります。

import Java.util.stream.IntStream;
import static Java.util.stream.IntStream.range;

public class StackOverflowTest {
    public static void main(String... args) {
        int[][] arr = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
        // Map the two dimensional array with indices.
        final IntStream intStream = range(0, arr.length).flatMap(row -> range(0, arr[row].length).map(col -> {
            final int element = arr[row][col];
            // E.g. multiply elements in odd numbered rows and columns by two.
            return row % 2 == 1 || col % 2 == 1 ? element * 2 : element;
        }));
        // Prints "1 4 3 8 10 12 7 16 9 ".
        intStream.forEachOrdered(n -> System.out.print(n + " "));
    }
}
0
Alex K.