This question already has an answer here:
这个问题已经有了答案:
- How do I do a deep copy of a 2d array in Java? 5 answers
- 如何在Java中对2d数组进行深度复制?5个回答
Edit 2: Below is a code snippet based on DuffyMo's response that illustrates how to get around the limitations of cloning for multidimensional arrays using System.arraycopy.
编辑2:下面是一个基于DuffyMo的响应的代码片段,它演示了如何使用System.arraycopy来绕过克隆多维数组的限制。
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
}
}
[ORIGINAL QUESTION] What's a simple way to (fully) clone a multidimensional array in java? This program illustrates my problem.
在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();
}
}
When the above code is run, arrayMaster changes as well as arrayChanges, contrary to my intentions. Thinking that I could clone each single dimensional array member of arrayMaster, I tried to get around the problem with this:
当上面的代码运行时,arrayMaster更改和arrayChanges,与我的意图相反。考虑到我可以克隆arrayMaster的每个单维数组成员,我试图解决这个问题:
for (int iter = 0; iter < arrayMaster.length; iter++) {
arrayChanges[iter] = arrayMaster[iter].clone();
}
but when I run the code that gives a NullPointerException for some reason. Is writing a method that loops through the individual integer values of the arrays my only option?
但是,当我运行代码时,由于某种原因,它给出了NullPointerException。编写一个遍历数组的单个整数值的方法是我唯一的选择吗?
Thanks.
谢谢。
EDIT 1: This doesn't fix the problem either.
编辑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();
}
}
2 个解决方案
#1
14
When the above code is run, arrayMaster changes as well as arrayChanges, contrary to my intentions.
当运行上述代码时,arrayMaster和arrayChanges都会发生变化,这与我的意图相反。
The line
这条线
static private int[][] arrayChanges = arrayMaster;
is the culprit. This line makes arrayChanges
and arrayMaster
point to the same object, so a change to either one is visible when you access the object from either.
是罪魁祸首。这一行使arrayChanges和arrayMaster指向同一个对象,因此当您从其中一个对象访问该对象时,可以看到对其中任何一个对象的更改。
EDIT: What happens whenever you clone one dimension of a multidimensional array
编辑:当你克隆一个多维数组的一个维度时会发生什么
As Eric Lippert explains, an array is conceptually a list of variables. If you just assign another variable to point to the same array a la static private int[][] arrayChanges = arrayMaster;
, you haven't changed the set of variables at all. You haven't created any new variables except for arrayChanges
, so you haven't gotten more memory from the operating system/JVM, so any change you make to arrayMaster
is applied to arrayChanges
and vice versa.
正如Eric Lippert所解释的,数组在概念上是一个变量列表。如果您只是指定另一个变量指向相同的数组,一个la static private int[] arrayChanges = arrayMaster;,您根本没有改变变量集。除了arrayChanges之外,您没有创建任何新变量,所以您没有从操作系统/JVM获得更多内存,所以您对arrayMaster的任何更改都应用于arrayChanges,反之亦然。
Now let's look at a two-dimensional array. In Java, a two-dimensional array is a list of variables that happens to have the property that each one of these variables refers to a one-dimensional array. So, whenever you clone a two-dimensional array, you create a new list of variables, each pointing in the same place that the old variables pointed in. So, you have gained a little in that you can safely write arrayChanges[0] = new int[10]
without affecting arrayMaster
, but as soon as you start referencing arrayChanges[i][j]
you are still referencing the same second-level arrays that arrayMaster
references. What you really want in order to deep-copy a two-dimensional array of ints is
现在我们来看一个二维数组。在Java中,二维数组是一个变量列表,它碰巧具有这些变量中的每个都引用一个一维数组的属性。因此,无论何时克隆一个二维数组,都要创建一个新的变量列表,每个变量都指向旧变量指向的位置。因此,您可以安全地编写arrayChanges[0] = new int[10]而不影响arrayMaster,但是一旦您开始引用arrayChanges[i][j],您仍然在引用arrayMaster引用的相同的二级数组。你真正想要的是为了深度复制一个二维的ints数组
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;
}
To those who may look at this answer in the future: yes, it is better replace int
with T
here and make the method generic, but for this purpose a more concrete deep copy method is simpler to explain well.
对于那些将来可能会看到这个答案的人来说:是的,最好在这里用T替换int,使方法成为通用的,但是为了这个目的,更具体的深层复制方法更容易解释。
#2
16
clone
does a "shallow" copy. That is, the outermost array is duplicated, but the values stored in it are unchanged. So if you have A1 = { B1, B2, B3 } and clone that into A2, A2's initial contents will be { B1, B2, B3 }. If you change A1 to { C1, B2, B3 } then A2 will remain unchanged, but if you change the contents of B1 (without replacing it) then A2 will "see" that change.
克隆做一个“浅”拷贝。也就是说,最外层的数组是重复的,但是其中存储的值是不变的。如果你有A1 = {B1, B2, B3}把它克隆成A2, A2的初始内容是{B1, B2, B3}。如果你将A1改为{C1, B2, B3},那么A2将保持不变,但是如果你改变B1的内容(不替换它),A2将“看到”这个变化。
To accomplish what you want you must loop through the outer array and clone
the elements of that outer array (which are the inner arrays).
为了实现您想要的效果,您必须循环遍历外部数组并克隆该外部数组的元素(即内部数组)。
Pidgin Java:
洋泾浜Java:
int[][] A2 = A1.clone();
for (int i = 0; i < A2.length; i++) {
A2[i] = A2[i].clone();
}
#1
14
When the above code is run, arrayMaster changes as well as arrayChanges, contrary to my intentions.
当运行上述代码时,arrayMaster和arrayChanges都会发生变化,这与我的意图相反。
The line
这条线
static private int[][] arrayChanges = arrayMaster;
is the culprit. This line makes arrayChanges
and arrayMaster
point to the same object, so a change to either one is visible when you access the object from either.
是罪魁祸首。这一行使arrayChanges和arrayMaster指向同一个对象,因此当您从其中一个对象访问该对象时,可以看到对其中任何一个对象的更改。
EDIT: What happens whenever you clone one dimension of a multidimensional array
编辑:当你克隆一个多维数组的一个维度时会发生什么
As Eric Lippert explains, an array is conceptually a list of variables. If you just assign another variable to point to the same array a la static private int[][] arrayChanges = arrayMaster;
, you haven't changed the set of variables at all. You haven't created any new variables except for arrayChanges
, so you haven't gotten more memory from the operating system/JVM, so any change you make to arrayMaster
is applied to arrayChanges
and vice versa.
正如Eric Lippert所解释的,数组在概念上是一个变量列表。如果您只是指定另一个变量指向相同的数组,一个la static private int[] arrayChanges = arrayMaster;,您根本没有改变变量集。除了arrayChanges之外,您没有创建任何新变量,所以您没有从操作系统/JVM获得更多内存,所以您对arrayMaster的任何更改都应用于arrayChanges,反之亦然。
Now let's look at a two-dimensional array. In Java, a two-dimensional array is a list of variables that happens to have the property that each one of these variables refers to a one-dimensional array. So, whenever you clone a two-dimensional array, you create a new list of variables, each pointing in the same place that the old variables pointed in. So, you have gained a little in that you can safely write arrayChanges[0] = new int[10]
without affecting arrayMaster
, but as soon as you start referencing arrayChanges[i][j]
you are still referencing the same second-level arrays that arrayMaster
references. What you really want in order to deep-copy a two-dimensional array of ints is
现在我们来看一个二维数组。在Java中,二维数组是一个变量列表,它碰巧具有这些变量中的每个都引用一个一维数组的属性。因此,无论何时克隆一个二维数组,都要创建一个新的变量列表,每个变量都指向旧变量指向的位置。因此,您可以安全地编写arrayChanges[0] = new int[10]而不影响arrayMaster,但是一旦您开始引用arrayChanges[i][j],您仍然在引用arrayMaster引用的相同的二级数组。你真正想要的是为了深度复制一个二维的ints数组
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;
}
To those who may look at this answer in the future: yes, it is better replace int
with T
here and make the method generic, but for this purpose a more concrete deep copy method is simpler to explain well.
对于那些将来可能会看到这个答案的人来说:是的,最好在这里用T替换int,使方法成为通用的,但是为了这个目的,更具体的深层复制方法更容易解释。
#2
16
clone
does a "shallow" copy. That is, the outermost array is duplicated, but the values stored in it are unchanged. So if you have A1 = { B1, B2, B3 } and clone that into A2, A2's initial contents will be { B1, B2, B3 }. If you change A1 to { C1, B2, B3 } then A2 will remain unchanged, but if you change the contents of B1 (without replacing it) then A2 will "see" that change.
克隆做一个“浅”拷贝。也就是说,最外层的数组是重复的,但是其中存储的值是不变的。如果你有A1 = {B1, B2, B3}把它克隆成A2, A2的初始内容是{B1, B2, B3}。如果你将A1改为{C1, B2, B3},那么A2将保持不变,但是如果你改变B1的内容(不替换它),A2将“看到”这个变化。
To accomplish what you want you must loop through the outer array and clone
the elements of that outer array (which are the inner arrays).
为了实现您想要的效果,您必须循环遍历外部数组并克隆该外部数组的元素(即内部数组)。
Pidgin Java:
洋泾浜Java:
int[][] A2 = A1.clone();
for (int i = 0; i < A2.length; i++) {
A2[i] = A2[i].clone();
}