Java 复制数组
- 数组赋值运算符:在Java中,使用赋值运算符(
=
)复制数组时,如果修改原数组,副本数组也会相应改变,因为它们引用同一个数组对象(浅拷贝)。 - 使用循环复制数组:通过循环遍历数组并逐个复制元素,可以创建一个新的数组对象,从而避免原数组修改时对副本的影响(深拷贝)。
- System.arraycopy() 和 Arrays.copyOfRange() 方法:
System.arraycopy()
和Arrays.copyOfRange()
是高效的数组复制方法,允许复制数组的特定部分,创建独立的新数组对象。
在 Java 中,我们可以将一个数组复制到另一个数组中。有几种技术可以用来复制 Java 中的数组。
1. 使用赋值运算符复制数组
让我们看一个例子,
class Main {
public static void main(String[] args) {
int [] numbers = {1, 2, 3, 4, 5, 6};
int [] positiveNumbers = numbers; // 复制数组
for (int number: positiveNumbers) {
System.out.print(number + ", ");
}
}
}
输出:
1, 2, 3, 4, 5, 6
在上面的例子中,我们使用了赋值运算符(=
)来将一个名为 numbers
的数组复制到另一个名为 positiveNumbers
的数组。
这种技术是最简单的,也是有效的。然而,这种技术存在一个问题。如果我们改变一个数组的元素,另一个数组的对应元素也会发生变化。例如,
class Main {
public static void main(String[] args) {
int [] numbers = {1, 2, 3, 4, 5, 6};
int [] positiveNumbers = numbers; // 复制数组
// 改变第一个数组的值
numbers[0] = -1;
// 打印第二个数组
for (int number: positiveNumbers) {
System.out.print(number + ", ");
}
}
}
输出:
-1, 2, 3, 4, 5, 6
这里,我们可以看到我们改变了 numbers
数组的一个值。当我们打印 positiveNumbers
数组时,我们可以看到相同的值也发生了变化。
这是因为两个数组引用同一个数组对象。这是浅拷贝的原因。要了解更多关于浅拷贝的信息,请访问 浅拷贝。
现在,为了在复制数组时创建新的数组对象,我们需要深拷贝而不是浅拷贝。
2. 使用循环结构来复制数组
让我们看一个例子:
import java.util.Arrays;
class Main {
public static void main(String[] args) {
int [] source = {1, 2, 3, 4, 5, 6};
int [] destination = new int[6];
// 遍历并从 source 复制元素到 destination
for (int i = 0; i < source.length; ++i) {
destination[i] = source[i];
}
// 将数组转换为字符串
System.out.println(Arrays.toString(destination));
}
}
输出:
[1, 2, 3, 4, 5, 6]
在上面的例子中,我们使用了 for
循环遍历源数组的每个元素。在每次迭代中,我们都将元素从 source
数组复制到 destination
数组。
这里,source 和 destination 数组引用不同的对象(深拷贝)。因此,如果一个数组的元素发生了变化,另一个数组的对应元素不会改变。
请注意这个语句,
System.out.println(Arrays.toString(destination));
这里,使用了 toString()
方法将数组转换为字符串。要了解更多,请访问 toString() 方法(官方 Java 文档)。
3. 使用 arraycopy() 方法复制数组
在 Java 中,System 类包含一个名为 arraycopy()
的方法来复制数组。与上述两种方法相比,这种方法是复制数组的更好选择。
arraycopy()
方法允许您将源数组的指定部分复制到目标数组中。例如,
arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
这里,
src
- 您想要复制的源数组srcPos
- 源数组中的起始位置(索引)dest
- 目标数组,元素将从源数组复制到此处destPos
- 目标数组中的起始位置(索引)length
- 要复制的元素数量
让我们看一个例子:
// 使用 Arrays.toString() 方法
import java.util.Arrays;
class Main {
public static void main(String[] args) {
int[] n1 = {2, 3, 12, 4, 12, -2};
int[] n3 = new int[5];
// 创建 n1 数组长度的 n2 数组
int[] n2 = new int[n1.length];
// 将整个 n1 数组复制到 n2
System.arraycopy(n1, 0, n2, 0, n1.length);
System.out.println("n2 = " + Arrays.toString(n2));
// 从 n1 数组索引 2 开始复制元素
// 将元素复制到 n3 数组的索引 1
// 将复制 2 个元素
System.arraycopy(n1, 2, n3, 1, 2);
System.out.println("n3 = " + Arrays.toString(n3));
}
}
输出:
n2 = [2, 3, 12, 4, 12, -2]
n3 = [0, 12, 4, 0, 0]
在上面的例子中,我们使用了 arraycopy()
方法,
System.arraycopy(n1, 0, n2, 0, n1.length)
- 将n1
数组的全部元素复制到n2
数组System.arraycopy(n1, 2, n3, 1, 2)
- 将n1
数组从索引2
开始的2
个元素复制到n3
数组从索引1
开始的位置
可以看到,int
类型数组的元素的默认初始值为 0。
4. 使用 copyOfRange() 方法复制数组
我们还可以使用 Java Arrays 类中定义的 copyOfRange() 方法来复制数组。例如,
// 使用 toString() 和 copyOfRange() 方法
import java.util.Arrays;
class ArraysCopy {
public static void main(String[] args) {
int[] source = {2, 3, 12, 4, 12, -2};
// 将整个源数组复制到目标数组
int[] destination1 = Arrays.copyOfRange(source, 0, source.length);
System.out.println("destination1 = " + Arrays.toString(destination1));
// 复制从索引 2 到 5(不包括 5)的元素
int[] destination2 = Arrays.copyOfRange(source, 2, 5);
System.out.println("destination2 = " + Arrays.toString(destination2));
}
}
输出
destination1 = [2, 3, 12, 4, 12, -2]
destination2 = [12, 4, 12]
在上面的例子中,请注意这一行,
int[] destination1 = Arrays.copyOfRange(source, 0, source
.length);
这里,我们可以看到我们正在同时创建 destination1
数组并将 source
数组复制到其中。我们在调用 copyOfRange()
方法之前并未创建 destination1
数组。要了解更多关于这个方法,请访问 Java copyOfRange。
5. 使用循环复制 2d 数组
与一维数组类似,我们也可以使用 for
循环来复制二维数组。例如,
import java.util.Arrays;
class Main {
public static void main(String[] args) {
int[][] source = {
{1, 2, 3, 4},
{5, 6},
{0, 2, 42, -4, 5}
};
int[][] destination = new int[source.length][];
for (int i = 0; i < destination.length; ++i) {
// 为目标数组的每一行分配空间
destination[i] = new int[source[i].length];
for (int j = 0; j < destination[i].length; ++j) {
destination[i][j] = source[i][j];
}
}
// 显示目标数组
System.out.println(Arrays.deepToString(destination));
}
}
输出:
[[1, 2, 3, 4], [5, 6], [0, 2, 42, -4, 5]]
在上述程序中,请注意这一行,
System.out.println(Arrays.deepToString(destination);
这里,使用了 deepToString()
方法更好地表示二维数组。要了解更多,请访问 Java deepToString()。
使用 arraycopy() 复制 2d 数组
为了使上述代码更简单,我们可以像一维数组一样,使用 System.arraycopy()
替换内部循环。例如,
import java.util.Arrays;
class Main {
public static void main(String[] args) {
int[][] source = {
{1, 2, 3, 4},
{5, 6},
{0, 2, 42, -4, 5}
};
int[][] destination = new int[source.length][];
for (int i = 0; i < source.length; ++i) {
// 为目标数组的每一行分配空间
destination[i] = new int[source[i].length];
System.arraycopy(source[i], 0, destination[i], 0, destination[i].length);
}
// 显示目标数组
System.out.println(Arrays.deepToString(destination));
}
}
输出:
[[1, 2, 3, 4], [5, 6], [0, 2, 42, -4, 5]]
这里,我们可以看到,通过使用 arraycopy()
方法替换内部 for
循环,我们得到了相同的输出。