这一节中将研究java数组拷贝的不同方法。Java提供了内置方法来复制数组。无论需要数组的完整副本还是部分副本,都可以使用java内置类轻松完成。
在java中复制数组有很多方法,下面我们来一个一个地学习和使用它们。
Object.clone()
-Object
类提供clone()
方法,由于java中的数组也是Object
,可以使用此方法实现完整的数组复制。如果想要数组的部分副本,则此方法不适合。System.arraycopy()
-System
类arraycopy()
是进行数组部分复制的最佳方法。它提供了一种指定要复制的元素总数以及源和目标数组索引位置的简便方法。例如,System.arraycopy(source,3,destination,2, 5)
将5
个元素从源复制到目标,从源的第3
个索引开始复制到目标的第2
个索引。Arrays.copyOf()
- 如果要复制数组的前几个元素或数组的完整副本,可以使用此方法。显然它不像System.arraycopy()
那样通用,但它也不会让人感到困惑和易于使用。此方法在内部使用System arraycopy()
方法。Arrays.copyOfRange()
- 如果要复制数组中的少数元素,而起始索引不是0
,则可以使用此方法复制部分数组。同样,此方法也使用Systemarraycopy
方法本身。
这些是完整和部分数组复制的四种最有用的方法。请注意,所有这些内置方法都只是复制一维数组。
Java复制数组示例
下面让我们看一下使用简单java程序的这些java数组复制方法。
package com.journaldev.util;
import java.util.Arrays;
public class JavaArrayExample {
/**
* 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(" First five elements of array if available. Result array = "+Arrays.toString(destination));
destination = copyFirstFiveFieldsOfArrayUsingSystem(source1);
System.out.println(" First five elements of array if available. Result array = "+Arrays.toString(destination));
destination = copyFullArrayUsingSystem(source);
System.out.println(" full array using System.copyarray() function. Result array = "+Arrays.toString(destination));
destination = copyFullArrayUsingClone(source);
System.out.println(" full array using clone() function. Result array = "+Arrays.toString(destination));
destination = copyFullArrayUsingArrayOf(source);
System.out.println(" full array using Arrays.copyOf() function. Result array = "+Arrays.toString(destination));
destination = copyLastThreeUsingArrayOfRange(source);
System.out.println(" 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[] copyFullArrayUsingArrayOf(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[] copyLastThreeUsingArrayOfRange(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]
First five elements of array if available. Result array = [1, 2, 3, 4, 5]
First five elements of array if available. Result array = [1, 2, 3]
full array using System.copyarray() function. Result array = [1, 2, 3, 4, 5, 6, 7, 8, 9]
full array using clone() function. Result array = [1, 2, 3, 4, 5, 6, 7, 8, 9]
full array using Arrays.copyOf() function. Result array = [1, 2, 3, 4, 5, 6, 7, 8, 9]
last three elements using Arrays.copyOfRange() function. Result array = [7, 8, 9]
Java数组拷贝 - 浅拷贝
请注意,上面讨论用于数组复制的所有内置方法都执行浅拷贝,因此它们适用于原始数据类型和不可变对象(如String)。如果要复制可变对象数组,则应该自己编写深复制代码。下面是一个显示浅拷贝方法问题的程序。
import java.util.Arrays;
public class JavaArrayMutableObjects {
public static void main(String[] args) {
Employee e = new Employee("Maxsu");
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 = [Maxsu]
empArray2 = [Maxsu]
empArray1 = [David]
empArray2 = [David]
如上面所看到的那样,empArray2
也发生了变化,即使它从不是有意的。这可能会导致应用程序出现严重问题,因此最好编写自己的代码以进行深层复制数组。类似的情况是针对java对象克隆方法的。
下面是在这种情况下使用的完整数组副本的代码。也可以轻松地为此部分数组复制编写类似的内容。
import java.util.Arrays;
public class JavaArrayMutableObjects {
public static void main(String[] args) {
Employee e = new Employee("Maxsu");
Employee[] empArray1 = {e};
Employee[] empArray2 = full(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[] full(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 = [Maxsu]
empArray2 = [Maxsu]
empArray1 = [David]
empArray2 = [Pankaj]
如上所见,在深复制中,源和目标数组元素指的是不同的对象。所以他们是完全脱离的,如果改变其中一个对象,另一个对象将不受影响。