web-dev-qa-db-ja.com

Javaの多次元配列を含むArrays.fill

ループを使用せずにJavaで多次元配列を埋めるにはどうすればよいですか?

double[][] arr = new double[20][4];
Arrays.fill(arr, 0);

これにより、Java.lang.ArrayStoreException: Java.lang.Double

前もって感謝します!

51
Caroline

これは、double[][]double[]の配列であり、0.0を割り当てることができないためです(double[] vector = 0.0を実行するようなものです)。実際、Javaには真の多次元配列はありません。

それが起こると、Javaでは0.0はdoubleのデフォルト値です。したがって、newから取得すると、実際にはマトリックスはすでにゼロで埋められています。ただし、たとえば1.0で埋めたい場合は、次のことができます。

APIがループを使用せずにこれを解決する方法を提供するとは思わない。ただし、for-eachループを使用してこれを行うのは非常に簡単です。

double[][] matrix = new double[20][4];

// Fill each row with 1.0
for (double[] row: matrix)
    Arrays.fill(row, 1.0);
83
aioobe
double[][] arr = new double[20][4];
Arrays.fill(arr[0], 0);
Arrays.fill(arr[1], 0);
Arrays.fill(arr[2], 0);
Arrays.fill(arr[3], 0);
Arrays.fill(arr[4], 0);
Arrays.fill(arr[5], 0);
Arrays.fill(arr[6], 0);
Arrays.fill(arr[7], 0);
Arrays.fill(arr[8], 0);
Arrays.fill(arr[9], 0);
Arrays.fill(arr[10], 0);
Arrays.fill(arr[11], 0);
Arrays.fill(arr[12], 0);
Arrays.fill(arr[13], 0);
Arrays.fill(arr[14], 0);
Arrays.fill(arr[15], 0);
Arrays.fill(arr[16], 0);
Arrays.fill(arr[17], 0);
Arrays.fill(arr[18], 0);
Arrays.fill(arr[19], 0);
60
trojanfoe

OPはこの問題を解決する方法を尋ねましたループなし!なんらかの理由で、最近ではループを避けることが流行しています。どうしてこれなの?おそらく、mapreducefilter、および友人、およびeachのようなメソッドを使用すると、ループを非表示にしてプログラムの冗長性を削減し、一種のクールな処理を実現できます。同じことが本当に素晴らしいUnixパイプラインにも当てはまります。またはjQueryコード。ループなしで見栄えが良くなります。

しかし、Javaにはmapメソッドがありますか?実際にはありませんが、Functionまたはevalを持つexecインターフェイスで定義できます。方法は難しくありませんし、良い練習になるでしょう。

これを行う別の方法ループなしは、末尾再帰を使用することです。はい、それは一種のばかげたものであり、誰も実際にそれを使用することはありませんが、おそらく、この場合はループが正常であることを示しています。それにもかかわらず、「まだ別のループフリーの例」を示して、楽しむために、ここにあります:

import Java.util.Arrays;
public class FillExample {
    private static void fillRowsWithZeros(double[][] a, int rows, int cols) {
        if (rows >= 0) {
            double[] row = new double[cols];
            Arrays.fill(row, 0.0);
            a[rows] = row;
            fillRowsWithZeros(a, rows - 1, cols);
        }
    }

    public static void main(String[] args) {
        double[][] arr = new double[20][4];
        fillRowsWithZeros(arr, arr.length - 1, arr[0].length);
        System.out.println(Arrays.deepToString(arr));
    }
}

きれいではありませんが、OPの質問への回答には、explicitループはありません。

9
Ray Toal

Per Java 8のように、この方法を使用できます。

double[][] arr = new double[20][4]; Arrays.stream(arr).forEach(a -> Arrays.fill(a, 0));

多次元配列の値をより適切にスマートに初期化できます。

5
Bipool

ループを使用せずにJavaで多次元配列を埋めるにはどうすればよいですか?

多次元配列は単なる配列の配列であり、fill(...)は配列の型と渡した値をチェックしません(この責任は開発者にあります)。

したがって、ループを使用せずに多次元配列を適切に埋めることはできません。

CやC++のような言語とは異なり、Java配列はオブジェクトであり、多次元配列では最後のレベルを除くすべてが他のArrayオブジェクトへの参照を含むことに注意してください。これについて100%確信はありませんが、ほとんどの場合、メモリに分散されているため、C/C++でできるように、ループなしで連続ブロックを埋めることはできません。

4
Thomas

答えの拡張として、私はこの投稿を見つけましたが、4次元配列を埋めようとしていました。元の例は2次元配列のみですが、質問は「多次元」です。これに関する新しい質問を投稿したくありませんでした...

同じ方法を使用できますが、それらをネストして、最終的に1次元配列に到達する必要があります。

fourDArray = new float[10][10][10][1];
// Fill each row with null
for (float[][][] row: fourDArray)
{
    for (float[][] innerRow: row)
    {
        for (float[] innerInnerRow: innerRow)
        {
        Arrays.fill(innerInnerRow, -1000);
        }
    }
};
3
k3yz101

私たち全員が時々そこにいたことを願ってはいけない
<T>void Java.util.Arrays.deepFill(T[]…multiDimensional)。問題が始まる
_Object threeByThree[][] = new Object[3][3];_
_threeByThree[1] = null;_および
_threeByThree[2][1] = new int[]{42};_は完全に合法です。
(_Object twoDim[]final[]_のみが正当であり、明確に定義されている場合...)
(以下のパブリックメソッドのいずれかを使用すると、呼び出し元のソースコードからループが保持されます。
ループをまったく使用しない場合は、ループを使用し、再帰を使用してArrays.fill()(!)を呼び出します。)

_/** Fills matrix {@code m} with {@code value}.
 * @return {@code m}'s dimensionality.
 * @throws Java.lang.ArrayStoreException if the component type
 *  of a subarray of non-zero length at the bottom level
 *  doesn't agree with {@code value}'s type. */
public static <T>int deepFill(Object[] m, T value) {
    Class<?> components; 
    if (null == m ||
        null == (components = m.getClass().getComponentType()))
        return 0;
    int dim = 0;
    do
        dim++;
    while (null != (components = components.getComponentType()));
    filler((Object[][])m, value, dim);
    return dim;
}
/** Fills matrix {@code m} with {@code value}.
 * @throws Java.lang.ArrayStoreException if the component type
 *  of a subarray of non-zero length at level {@code dimensions}
 *  doesn't agree with {@code value}'s type. */
public static <T>void fill(Object[] m, T value, int dimensions) {
    if (null != m)
        filler(m, value, dimensions);
}

static <T>void filler(Object[] m, T value, int toGo) {
    if (--toGo <= 0)
        Java.util.Arrays.fill(m, value);
    else
        for (Object[] subArray : (Object[][])m)
            if (null != subArray)
                filler(subArray, value, toGo);
}
_
1
greybeard

Java 8を使用すると、次のように(明示的な)ループを使用せずに2次元配列を宣言および初期化できます。

int x = 20; // first dimension
int y = 4; // second dimension

double[][] a = IntStream.range(0, x)
                        .mapToObj(i -> new double[y])
                        .toArray(i -> new double[x][]);

これにより、デフォルト値(0.0の場合はdouble)。

使用する塗りつぶし値を明示的に定義する場合は、DoubleStreamを追加できます。

int x = 20; // first dimension
int y = 4; // second dimension
double v = 5.0; // fill value

double[][] a = IntStream
        .range(0, x)
        .mapToObj(i -> DoubleStream.generate(() -> v).limit(y).toArray())
        .toArray(i -> new double[x][]);
0
public static Object[] fillArray(Object[] arr,Object item){
    Arrays.fill(arr, item);
    return arr;
}
Character[][] maze = new Character[10][10];
    fillArray(maze, fillArray(maze[0], '?'));

    for(int i = 0;i<10;i++){
        System.out.println();
        for(int j = 0;j<10;j++){
            System.out.print(maze[i][j]);
        }
    }

これがうまくいくことを願っています

0
Ahmed Mazher

簡単な言葉でJavaこのようなAPIを提供しない。ループを反復処理する必要があり、fillメソッドを使用して2D配列を1つのループで埋めることができる。

      int row = 5;
      int col = 6;
      int cache[][]=new int[row][col];
      for(int i=0;i<=row;i++){
          Arrays.fill(cache[i]);
      }
0
Sanjeev Guglani