主题
  • 默认模式
  • 浅蓝色模式
  • 淡绿色模式
  • 深夜模式

Java 数组复制

在 Java 编程中,数组复制是一项基础但至关重要的操作。由于数组是对象,简单的赋值操作(array2 = array1)只会创建引用副本而非真正的数据副本,这可能导致意外的副作用。因此,掌握正确的数组复制方法对于编写健壮、可维护的代码至关重要。Java 提供了多种数组复制机制,每种方法都有其特定的适用场景和性能特征。

在学习数组复制前需,需要了解复制引用类型数组时的核心概念

  • 浅拷贝:只复制数组本身的引用地址。新数组和原数组中的元素指向的是同一个对象。
  • 深拷贝:不仅复制数组本身,还会递归地复制数组中的所有对象,创建完全独立的副本。

在 Java 中实现数组复制有多种方式,本文会按照从简便到灵活的顺序依次介绍数组的复制方法。

Java 数组复制结构图


使用 Arrays.copyOf 方法 (最常用、最简洁)

java.util.Arrays 类提供的copyOf方法是最常用且推荐的复制方式之一。它封装了数组创建的细节,只需一行代码就能完成复制,并且可以灵活指定新数组的长度。当新数组长度大于原数组时,多出的元素会自动填充默认值;当长度较小时,则会截断原数组。这种方法在可读性和功能性之间取得了很好的平衡,适用于绝大多数日常开发场景。

以下是一个简单的使用实例:

java
复制
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 实现,通常是速度最快的复制方法。它需要你预先创建好目标数组

以下是一个简单的使用实例:

java
复制
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方法,可以直接用于数组复制。

以下是一个简单的使用实例:

java
复制
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 循环迭代并逐个元素进行赋值,是实现该功能最为原始的方法。

以下是一个简单的使用实例:

java
复制
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]

从输出结果可以看出,使用循环手动复制数组能够实现基本的数组复制功能。虽然这种方法较为繁琐且容易出错,但它提供了最大的灵活性,允许开发者根据具体需求进行定制化处理,例如跳过某些元素或进行条件复制。对于引用类型数组,复制的是引用(浅拷贝)。



评论区 0
发表评论