Java 数组复制
在 Java 编程中,数组复制是一项基础但至关重要的操作。由于数组是对象,简单的赋值操作(array2 = array1)只会创建引用副本而非真正的数据副本,这可能导致意外的副作用。因此,掌握正确的数组复制方法对于编写健壮、可维护的代码至关重要。Java 提供了多种数组复制机制,每种方法都有其特定的适用场景和性能特征。
在学习数组复制前需,需要了解复制引用类型数组时的核心概念:
- 浅拷贝:只复制数组本身的引用地址。新数组和原数组中的元素指向的是同一个对象。
- 深拷贝:不仅复制数组本身,还会递归地复制数组中的所有对象,创建完全独立的副本。
在 Java 中实现数组复制有多种方式,本文会按照从简便到灵活的顺序依次介绍数组的复制方法。
使用 Arrays.copyOf 方法 (最常用、最简洁)
java.util.Arrays
类提供的copyOf
方法是最常用且推荐的复制方式之一。它封装了数组创建的细节,只需一行代码就能完成复制,并且可以灵活指定新数组的长度。当新数组长度大于原数组时,多出的元素会自动填充默认值;当长度较小时,则会截断原数组。这种方法在可读性和功能性之间取得了很好的平衡,适用于绝大多数日常开发场景。
以下是一个简单的使用实例:
import java.util.Arrays;
public class ArrayCopyExample {
public static void main(String[] args) {
int[] originalArray = {1, 2, 3, 4, 5};
// 复制一个长度相同的新数组
int[] copiedArray1 = Arrays.copyOf(originalArray, originalArray.length);
System.out.println("相同长度复制: " + Arrays.toString(copiedArray1)); // [1, 2, 3, 4, 5]
// 复制一个更长的数组,多出的部分会用默认值填充 (int的默认值是0)
int[] copiedArray2 = Arrays.copyOf(originalArray, 10);
System.out.println("更长数组复制: " + Arrays.toString(copiedArray2)); // [1, 2, 3, 4, 5, 0, 0, 0, 0, 0]
// 复制一个更短的数组
int[] copiedArray3 = Arrays.copyOf(originalArray, 3);
System.out.println("更短数组复制: " + Arrays.toString(copiedArray3)); // [1, 2, 3]
// 对于引用类型数组,复制的是引用(浅拷贝)
String[] strOriginal = {"Hello", "World"};
String[] strCopied = Arrays.copyOf(strOriginal, strOriginal.length);
System.out.println("引用类型复制前: " + Arrays.toString(strCopied));
strOriginal[0] = "Hi"; // 修改原数组
System.out.println("引用类型复制后: " + Arrays.toString(strCopied));
// 输出: [Hello, World] (因为String是不可变的,这里看起来是深拷贝,但其实不是)
// 如果是自定义对象,修改原数组中的对象会影响到复制数组中的对应对象
}
}
执行这个程序后,输出结果:
相同长度复制: [1, 2, 3, 4, 5]
更长数组复制: [1, 2, 3, 4, 5, 0, 0, 0, 0, 0]
更短数组复制: [1, 2, 3]
引用类型复制前: [Hello, World]
引用类型复制后: [Hello, World]
从输出结果可以看出,Arrays.copyOf
方法能够灵活地处理不同长度的数组复制需求。如果要复制的是引用类型数组,它复制的是引用地址(浅引用),因此修改原数组中的对象会影响到复制数组中的对应对象
使用 System.arraycopy 方法 (高效、底层)
这是一个本地(Native)方法,由 JVM 实现,通常是速度最快的复制方法。它需要你预先创建好目标数组。
以下是一个简单的使用实例:
public class ArrayCopyExample {
public static void main(String[] args) {
int[] source = {1, 2, 3, 4, 5, 6, 7, 8};
int[] destination = new int[10]; // 目标数组必须先创建好
// 将source数组中从索引2开始的3个元素,复制到destination数组从索引5开始的位置
System.arraycopy(source, 2, destination, 5, 3);
System.out.println("目标数组: " + Arrays.toString(destination));
// 输出: [0, 0, 0, 0, 0, 3, 4, 5, 0, 0]
// 也可以用于自身复制(重叠复制)
System.arraycopy(source, 1, source, 2, 3);
System.out.println("自身重叠复制后: " + Arrays.toString(source));
// 输出: [1, 2, 2, 3, 4, 6, 7, 8] (将索引1,2,3复制到了2,3,4的位置)
}
}
执行这个程序后,输出结果:
目标数组: [0, 0, 0, 0, 0, 3, 4, 5, 0, 0]
自身重叠复制后: [1, 2, 2, 3, 4, 6, 7, 8]
从输出结果可以看出,System.arraycopy
方法能够高效地将数组的一部分复制到另一个数组的指定位置。它也支持在同一数组内进行重叠复制,这在某些算法中非常有用。对于引用类型数组,复制的是引用(浅拷贝)。
使用 clone() 方法
所有数组都隐式继承了Object
类的clone()
方法,并被重写为public
方法,可以直接用于数组复制。
以下是一个简单的使用实例:
public class ArrayCopyExample {
public static void main(String[] args) {
int[] originalArray = {1, 2, 3, 4, 5};
int[] clonedArray = originalArray.clone();
System.out.println("Cloned array: " + Arrays.toString(clonedArray)); // [1, 2, 3, 4, 5]
// 修改原数组不会影响克隆的数组(对于基本类型)
originalArray[0] = 99;
System.out.println("原数组修改后: " + Arrays.toString(originalArray)); // [99, 2, 3, 4, 5]
System.out.println("克隆数组: " + Arrays.toString(clonedArray)); // [1, 2, 3, 4, 5]
}
}
执行这个程序后,输出结果:
Cloned array: [1, 2, 3, 4, 5]
原数组修改后: [99, 2, 3, 4, 5]
克隆数组: [1, 2, 3, 4, 5]
从输出结果可以看出,使用clone()
方法创建的数组是原数组的一个独立副本。修改原数组不会影响克隆的数组,适用于需要完整复制数组内容的场景。对于引用类型数组,复制的是引用(浅拷贝)。不如Arrays.copyOf
灵活(不能改变数组长度)。
使用循环手动复制(最基础)
通过 for 循环迭代并逐个元素进行赋值,是实现该功能最为原始的方法。
以下是一个简单的使用实例:
import java.util.Arrays;
public class ArrayCopyExample {
public static void main(String[] args) {
int[] originalArray = {1, 2, 3, 4, 5};
int[] newArray = new int[originalArray.length];
for (int i = 0; i < originalArray.length; i++) {
newArray[i] = originalArray[i];
}
System.out.println("手动复制数组: " + Arrays.toString(newArray));
}
}
执行这个程序后,输出结果:
手动复制数组: [1, 2, 3, 4, 5]
从输出结果可以看出,使用循环手动复制数组能够实现基本的数组复制功能。虽然这种方法较为繁琐且容易出错,但它提供了最大的灵活性,允许开发者根据具体需求进行定制化处理,例如跳过某些元素或进行条件复制。对于引用类型数组,复制的是引用(浅拷贝)。
反馈提交成功
感谢您的反馈,我们将尽快处理您的反馈