Java复制阵列– Java中的阵列复制

时间:2020-02-23 14:36:28  来源:igfitidea点击:

今天,我们将研究java数组复制的不同方法。
Java提供了内置方法来复制数组。
无论您要数组的完整副本还是部分副本,都可以使用Java内置类轻松完成。

Java复制数组

有许多方法可以在Java中复制数组。
让我们一一看一下。

  • Object.clone():Object类提供了clone()方法,并且由于Java中的数组也是Object,因此您可以使用此方法来实现完整的数组复制。
    如果要部分复制数组,则此方法不适合您。

  • System.arraycopy():系统类arraycopy()是对数组进行部分复制的最佳方法。
    它为您提供一种简单的方法来指定要复制的元素总数以及源和目标数组索引位置。
    例如," System.arraycopy(source,3,destination,2,5)"将从源的第三个索引到目标的第二个索引将5个元素从源复制到目标。

  • Arrays.copyOf():如果要复制数组的前几个元素或者数组的完整副本,则可以使用此方法。
    显然,它不像System.arraycopy()那样通用,但也不易混淆且易于使用。
    此方法在内部使用System arraycopy()方法。

  • Arrays.copyOfRange():如果要复制数组的几个元素(起始索引不为0),则可以使用此方法复制部分数组。
    同样,此方法也使用系统arraycopy方法本身。

因此,这是完整和部分阵列复制的四种最有用的方法。
请注意,所有这些内置方法都仅复制一维数组。

Java复制数组示例

现在,让我们看看这些Java数组复制方法在一个简单的Java程序中的作用。

package com.theitroad.util;

import java.util.Arrays;

public class JavaArrayCopyExample {

  /**
   * This class shows different methods for copy array in java
   * @param args
   */
  public static void main(String[] args) {
      int[] source = {1,2,3,4,5,6,7,8,9};
      int[] source1 = {1,2,3};
      int[] destination=null;
      System.out.println("Source array = "+Arrays.toString(source));
      
      destination = copyFirstFiveFieldsOfArrayUsingSystem(source);
      System.out.println("Copy First five elements of array if available. Result array = "+Arrays.toString(destination));
      
      destination = copyFirstFiveFieldsOfArrayUsingSystem(source1);
      System.out.println("Copy First five elements of array if available. Result array = "+Arrays.toString(destination));
      
      destination = copyFullArrayUsingSystem(source);
      System.out.println("Copy full array using System.copyarray() function. Result array = "+Arrays.toString(destination));
      
      destination = copyFullArrayUsingClone(source);
      System.out.println("Copy full array using clone() function. Result array = "+Arrays.toString(destination));
      
      destination = copyFullArrayUsingArrayCopyOf(source);
      System.out.println("Copy full array using Arrays.copyOf() function. Result array = "+Arrays.toString(destination));
      
      destination = copyLastThreeUsingArrayCopyOfRange(source);
      System.out.println("Copy last three elements using Arrays.copyOfRange() function. Result array = "+Arrays.toString(destination));
  }

  /**
   * This method copy full array using Arrays.copyOf() function
   * @param source
   * @return
   */
  private static int[] copyFullArrayUsingArrayCopyOf(int[] source) {
      return Arrays.copyOf(source, source.length);
  }
  
  /**
   * This method copy partial array (last 3 elements) using 
   * Arrays.copyOfRange() function
   * @param source
   * @return
   */
  private static int[] copyLastThreeUsingArrayCopyOfRange(int[] source) {
      //length check is necessary to avoid java.lang.ArrayIndexOutOfBoundsException
      //but for simplicity I am not doing that
      return Arrays.copyOfRange(source, source.length-3, source.length);
  }

  /**
   * This method copy full array using clone() function
   * @param source
   * @return
   */
  private static int[] copyFullArrayUsingClone(int[] source) {
      return source.clone();
  }

  /**
   * This method copy full array using System.arraycopy() function
   * @param source
   * @return
   */
  private static int[] copyFullArrayUsingSystem(int[] source) {
      int[] temp=new int[source.length];
      System.arraycopy(source, 0, temp, 0, source.length);
      return temp;
  }

  /**
   * This method copy full first five elements of array 
   * using System.arraycopy() function
   * @param source
   * @return
   */
  private static int[] copyFirstFiveFieldsOfArrayUsingSystem(int[] source) {
      if(source.length > 5){
          int[] temp=new int[5];
          System.arraycopy(source, 0, temp, 0, 5);
          return temp;
      }else{
          int[] temp=new int[source.length];
          System.arraycopy(source, 0, temp, 0, source.length);
          return temp;
      }
      
  }

}

上面程序的输出是:

Source array = [1, 2, 3, 4, 5, 6, 7, 8, 9]
Copy First five elements of array if available. Result array = [1, 2, 3, 4, 5]
Copy First five elements of array if available. Result array = [1, 2, 3]
Copy full array using System.copyarray() function. Result array = [1, 2, 3, 4, 5, 6, 7, 8, 9]
Copy full array using clone() function. Result array = [1, 2, 3, 4, 5, 6, 7, 8, 9]
Copy full array using Arrays.copyOf() function. Result array = [1, 2, 3, 4, 5, 6, 7, 8, 9]
Copy last three elements using Arrays.copyOfRange() function. Result array = [7, 8, 9]

Java阵列复制–浅复制

请注意,上面讨论的所有用于数组复制的内置方法都执行浅表复制,因此它们适用于原始数据类型和不可变对象(例如String)。
如果要复制可变对象的数组,则应自己编写用于深度复制的代码来实现。
下面是一个程序,显示浅拷贝方法的问题。

import java.util.Arrays;

public class JavaArrayCopyMutableObjects {

	public static void main(String[] args) {
		Employee e = new Employee("hyman");
		
		Employee[] empArray1 = {e};
		
		Employee[] empArray2 = new Employee[empArray1.length];
				
		System.arraycopy(empArray1, 0, empArray2, 0, empArray1.length);
		
		System.out.println("empArray1 = "+Arrays.toString(empArray1));
		System.out.println("empArray2 = "+Arrays.toString(empArray2));
		
		//Let's change empArray1
		empArray1[0].setName("David");
		
		System.out.println("empArray1 = "+Arrays.toString(empArray1));
		System.out.println("empArray2 = "+Arrays.toString(empArray2));
		
	}

}

class Employee {
	private String name;

	public Employee(String n) {
		this.name = n;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	@Override
	public String toString() {
		return this.name;
	}
}

现在,当我们运行上面的程序时,下面是生成的输出。

empArray1 = [hyman]
empArray2 = [hyman]
empArray1 = [David]
empArray2 = [David]

正如您所看到的,即使没有意图,empArray2也发生了变化。
这可能会在您的应用程序中引起严重的问题,因此最好编写自己的代码以进行数组的深层复制。
Java对象克隆方法也有类似情况。

下面是在这种情况下使用的完整数组复制的代码。
您也可以轻松地为部分数组复制编写类似的内容。

import java.util.Arrays;

public class JavaArrayCopyMutableObjects {

	public static void main(String[] args) {
		Employee e = new Employee("hyman");
		
		Employee[] empArray1 = {e};
		
		Employee[] empArray2 = fullCopy(empArray1);
		
		System.out.println("empArray1 = "+Arrays.toString(empArray1));
		System.out.println("empArray2 = "+Arrays.toString(empArray2));
		
		//Let's change empArray1
		empArray1[0].setName("David");
		
		System.out.println("empArray1 = "+Arrays.toString(empArray1));
		System.out.println("empArray2 = "+Arrays.toString(empArray2));

		
	}

	private static Employee[] fullCopy(Employee[] source) {
		Employee[] destination = new Employee[source.length];
		
		for(int i=0; i< source.length; i++) {
			Employee e = source[i];
			Employee temp = new Employee(e.getName());
			destination[i] = temp;
		}
		return destination;
	}

}

class Employee {
	private String name;

	public Employee(String n) {
		this.name = n;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	@Override
	public String toString() {
		return this.name;
	}
}

现在,当我们运行上述程序时,产生的输出为:

empArray1 = [hyman]
empArray2 = [hyman]
empArray1 = [David]
empArray2 = [hyman]

如您所见,在深度复制中,我们的源和目标数组元素引用了不同的对象。
因此,它们是完全分离的,如果我们更改其中一个,则另一个将不受影响。