web-dev-qa-db-ja.com

Javaで2次元配列をコピーするにはどうすればよいですか?

私が取り組んでいるプロジェクトのために、かなり大きな2次元配列のコピーを作成する必要があります。 2つの2D配列があります。

int[][]current;
int[][]old;

コピーを行う方法も2つあります。電流は定期的に更新されているため、アレイをコピーする必要があります。

public void old(){
  old=current
}

そして

public void keepold(){
  current=old
}

ただし、これは機能しません。古いものを呼び出して、currentを更新してからkeepoldを呼び出した場合、currentは元の値と等しくありません。これはなぜでしょうか?

ありがとう

35
badcoder

current=oldまたはold=currentは、2つの配列が同じものを参照するようにします。したがって、後でcurrentを変更すると、oldも変更されます。配列の内容を別の配列にコピーするには、forループを使用します

for(int i=0; i<old.length; i++)
  for(int j=0; j<old[i].length; j++)
    old[i][j]=current[i][j];

PS:1次元配列の場合、 Arrays.copyOf

38
Louis Rhys
/**
 * Clones the provided array
 * 
 * @param src
 * @return a new clone of the provided array
 */
public static int[][] cloneArray(int[][] src) {
    int length = src.length;
    int[][] target = new int[length][src[0].length];
    for (int i = 0; i < length; i++) {
        System.arraycopy(src[i], 0, target[i], 0, src[i].length);
    }
    return target;
}

このコードを変更して、オブジェクトのn次元配列をサポートすることは可能ですか?

任意の長さの配列をサポートし、srcとdestinationの次元が同じかどうかを確認する必要があります。 また、オブジェクトも配列である場合、各配列の各要素をコピーする必要がありますrecursively

これを投稿してからしばらく経ちましたが、n次元配列を作成する1つの方法の素敵な例を見つけましたクラス。このクラスは、コンストラクターでゼロ以上の整数を取り、各次元のそれぞれのサイズを指定します。このクラスは、基になるflat array Object[]次元と乗数の配列を使用して各要素のインデックスを計算します。 (これは、Cプログラミング言語で配列が行われる方法です。)

NDimensionalArrayのインスタンスをコピーすることは、他の2D配列をコピーするのと同じくらい簡単です。ただし、各NDimensionalArrayオブジェクトは同じ次元であると断言する必要があります。再帰がないため、これがおそらく最も簡単な方法です。これにより、表現とアクセスがはるかに簡単になります。

23
mbomb007

Java 8なので、ストリームAPIを使用:

int[][] copy = Arrays.stream(matrix).map(r -> r.clone()).toArray(int[][]::new);

rは、2Dマトリックスのrowを指します。

12

System.arraycopyを使用して多次元int配列をコピーする簡単な関数を書くことを解決しました

public static void arrayCopy(int[][] aSource, int[][] aDestination) {
    for (int i = 0; i < aSource.length; i++) {
        System.arraycopy(aSource[i], 0, aDestination[i], 0, aSource[i].length);
    }
}

または実際に私は私のユースケースのためにそれを改善しました:

/**
 * Clones the provided array
 * 
 * @param src
 * @return a new clone of the provided array
 */
public static int[][] cloneArray(int[][] src) {
    int length = src.length;
    int[][] target = new int[length][src[0].length];
    for (int i = 0; i < length; i++) {
        System.arraycopy(src[i], 0, target[i], 0, src[i].length);
    }
    return target;
}
9
Daniel Backman

次のようにすることもできます。

public static int[][] copy(int[][] src) {
    int[][] dst = new int[src.length][];
    for (int i = 0; i < src.length; i++) {
        dst[i] = Arrays.copyOf(src[i], src[i].length);
    }
    return dst;
}
4
Johnny Lim
current = old ;

割り当て操作は、ある配列の要素を別の配列にコピーしません。 currentマトリックスがoldマトリックスを参照するようにしているだけです。メンバーごとにコピーする必要があります。

1
Mahesh

Java 8を使用すると、これは

`int[][] destination=Arrays.stream(source)
                    .map(a ->  Arrays.copyOf(a, a.length))
                    .toArray(int[][]::new);
1
Rakesh Chauhan

ループを使用してこれを行う方法は次のとおりです。

public static int[][] makeCopy(int[][] array){
    b=new int[array.length][];

    for(int row=0; row<array.length; ++row){
        b[row]=new int[array[row].length];
        for(int col=0; col<b[row].length; ++col){
            b[row][col]=array[row][col];
        }
    }
    return b;
}
0

Javaはオブジェクトであり、すべてのオブジェクトは 参照渡し です。配列に別の名前を作成する代わりに、配列を実際に「コピー」するには、 System.arrayCopyは1次元配列を完全にコピーしますが、2次元配列はコピーしないことに注意してください。2D配列は実際には1Dの1D配列であることに注意してください。配列、およびarrayCopyは、同じ内部1D配列へのポインターをコピーします。

0
Sajid

私はこの機能を使用しています:

public static int[][] copy(final int[][] array) {
    if (array != null) {
        final int[][] copy = new int[array.length][];

        for (int i = 0; i < array.length; i++) {
            final int[] row = array[i];

            copy[i] = new int[row.length];
            System.arraycopy(row, 0, copy[i], 0, row.length);
        }

        return copy;
    }

    return null;
}

このアプローチの大きな利点は、次のような同じ行カウントを持たない配列もコピーできることです。

final int[][] array = new int[][] { { 5, 3, 6 }, { 1 } };
0
Niklas