跳到主要内容

Java 复制数组

提示
  1. 数组赋值运算符:在Java中,使用赋值运算符(=)复制数组时,如果修改原数组,副本数组也会相应改变,因为它们引用同一个数组对象(浅拷贝)。
  2. 使用循环复制数组:通过循环遍历数组并逐个复制元素,可以创建一个新的数组对象,从而避免原数组修改时对副本的影响(深拷贝)。
  3. 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 循环,我们得到了相同的输出。