16

編集 2: 以下は、System.arraycopy を使用して多次元配列のクローン作成の制限を回避する方法を示す DuffyMo の応答に基づくコード スニペットです。

import java.util.Arrays;

public class Randar {
public static int[][] arrayMaster = {{6,1}, {10,1}, {1,1}};
private static int[][] arrayChanges = new int[arrayMaster.length][2];

public Randar () {

}
public static void main(String[] args) {
    arrayChanges[0][0] = 0;
    resetArrays(arrayChanges, arrayMaster);
    arrayChanges[0][0] = 0;

    System.out.format("arrayMaster: %s, arrayChanges: %s", Arrays.deepToString(arrayMaster), Arrays.deepToString(arrayChanges));
}


public static void resetArrays(int[][] arrayChanges, int[][] arrayMaster) {
for (int a=0; a< arrayMaster.length; a++) {
System.arraycopy(arrayMaster[a], 0, arrayChanges[a], 0, arrayMaster[a].length);
}
// arrayChanges = arrayMaster.clone(); will NOT work as expected
}
}

[元の質問] Java で多次元配列を (完全に) 複製する簡単な方法は何ですか? このプログラムは私の問題を示しています。

import java.util.Arrays;

public class Randar {
public static int[][] arrayMaster = {{6,1}, {10,1}, {1,1}};
static private int[][] arrayChanges = arrayMaster;

public static void main(String[] args) {
    arrayChanges[0][0] = 0;
    resetArrays();

    System.out.format("arrayMaster: %s, arrayChanges: %s",Arrays.deepToString(arrayMaster), Arrays.deepToString(arrayChanges));
}


public static void resetArrays() {
arrayChanges = arrayMaster.clone();
}

}

上記のコードを実行すると、私の意図に反して、arrayChanges だけでなく arrayMaster も変更されます。arrayMaster の各単一次元配列メンバーを複製できると考えて、これで問題を回避しようとしました。

for (int iter = 0; iter < arrayMaster.length; iter++) {
    arrayChanges[iter] = arrayMaster[iter].clone();
    }

しかし、何らかの理由で NullPointerException を与えるコードを実行すると。配列の個々の整数値をループするメソッドを書くことは私の唯一のオプションですか?

ありがとう。

編集1:これでも問題は解決しません。

import java.util.Arrays;

public class Randar {
public int[][] arrayMaster = {{6,1}, {10,1}, {1,1}};
private int[][] arrayChanges = arrayMaster.clone();

public Randar () {

}
public static void main(String[] args) {
    Randar Randar1 = new Randar();
    Randar1.arrayChanges[0][0] = 0;
    resetArrays(Randar1.arrayChanges, Randar1.arrayMaster);
    Randar1.arrayChanges[0][0] = 0;

    System.out.format("arrayMaster: %s, arrayChanges: %s",     Arrays.deepToString(Randar1.arrayMaster), Arrays.deepToString(Randar1.arrayChanges));
}


public static void resetArrays(int[][] arrayChanges, int[][] arrayMaster) {
/*for (int a=0; a< arrayMaster.length; a++) {
System.arraycopy(arrayMaster[a].clone(), 0, arrayChanges[a], 0, arrayMaster[a].length);
} */
arrayChanges = arrayMaster.clone();
}
}
4

2 に答える 2

21

上記のコードを実行すると、私の意図に反して、arrayChanges だけでなく arrayMaster も変更されます。

この線

static private int[][] arrayChanges = arrayMaster;

が犯人です。この行は同じオブジェクトを作成arrayChangesしてarrayMasterポイントするため、いずれかからオブジェクトにアクセスすると、いずれかへの変更が表示されます。

編集:多次元配列の1つの次元を複製するとどうなりますか

Eric Lippert が説明しているように、配列は概念的には変数のリストです。同じ配列 a la を指すように別の変数を割り当てるだけではstatic private int[][] arrayChanges = arrayMaster;、変数のセットはまったく変更されていません。以外の新しい変数を作成していないarrayChangesため、オペレーティング システム/JVM からより多くのメモリを取得していないため、変更arrayMasterは に適用されarrayChanges、その逆も同様です。

次に、2 次元配列を見てみましょう。Java では、2 次元配列は変数のリストであり、たまたまこれらの変数のそれぞれが 1 次元配列を参照するというプロパティを持っています。したがって、2 次元配列を複製するときはいつでも、変数の新しいリストを作成し、それぞれが古い変数が指している場所と同じ場所を指しますarrayChanges[0] = new int[10]arrayMaster参照を開始するとすぐに、arrayChanges[i][j]参照する同じ第 2 レベルの配列をまだ参照していarrayMasterます。int の 2 次元配列をディープ コピーするために本当に必要なのは、

public static int[][] deepCopyIntMatrix(int[][] input) {
    if (input == null)
        return null;
    int[][] result = new int[input.length][];
    for (int r = 0; r < input.length; r++) {
        result[r] = input[r].clone();
    }
    return result;
}

将来この回答を見るかもしれない人へ:はい、ここに置き換えintTメソッドをジェネリックにする方が良いですが、この目的のためには、より具体的なディープコピーメソッドの方が簡単に説明できます。

于 2012-02-02T02:06:23.263 に答える
20

clone「浅い」コピーを行います。つまり、最も外側の配列が複製されますが、そこに格納されている値は変更されません。したがって、A1 = { B1, B2, B3 } があり、それを A2 に複製すると、A2 の初期コンテンツは { B1, B2, B3 } になります。A1 を { C1, B2, B3 } に変更すると、A2 は変更されませんが、B1 の内容を (置き換えずに) 変更すると、A2 はその変更を「認識」します。

clone目的を達成するには、外側の配列とその外側の配列の要素 (内側の配列) をループする必要があります。

ピジンジャワ:

int[][] A2 = A1.clone();
for (int i = 0; i < A2.length; i++) {
    A2[i] = A2[i].clone();
}
于 2012-02-02T03:08:49.890 に答える