2.java数组拷贝的3种方式和效率对比
Java语言中常用的数组拷贝方式有:for循环拷贝,通过Arrays.copyOf()方法,System.arraycopy和clone()方法拷贝。
1 测试场景
我们用最简单的整数数组来测试。首先创建一个整型数组,并且初始化数据。然后分别用这3种方式来拷贝数组同样的次数。来测分别试这三种情况的效率。
1.1 初始化数组
int len = 1000;
int[] arr0 = new int[len];
for (int i = 0; i < len; i++) {
arr0[i] = i;
}1.1 for循环拷贝数组
采用for循环遍历数组,然后根据数组下标对应赋值,来实现复制数组。
/** 1 for 循环拷贝*/
int[] arr1 = new int[len];
for (int i = 0; i < len; i++) {
arr1[i] = arr0[i];
}1.2 Arrays.copyOf拷贝数组
java.util.Arrays类中提供了一个copyOf()方法,通过这个方法可以实现数组复制。这个方法的原理是内部创建了一个数组对象,然后通过System.arraycopy来实现数组复制.
- copyOf方法源码
public static int[] copyOf(int[] original, int newLength) {
int[] copy = new int[newLength];
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}- System.arraycopy源码
System.arraycop方法是通过native方法,Java虚拟机内部实现的。
public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length);- 调用Arrays.copyOf()方法
int[] arr2 = Arrays.copyOf(arr0, arr0.length);1.3 System.arraycopy复制数组
System.arraycopy方法提供了从数组中截取一部分,生成一个新的数组,也是Arrays.copyOf()方法的底层实现。
int[] arr3 = new int[len];
System.arraycopy(arr0, 0, arr3, 0, arr0.length);1.4 clone()方法拷贝数组
Java的Object
int[] arr3 = arr0.clone();2 测试这几种复制方法
将上述4中复制方式,对一个长度1000的数组,复制一千万次,来看一下执行时间。
2.1 示例代码
package com.dashidan.profile1;
import java.util.Arrays;
/**
* 大屎蛋教程网-dashidan.com
* 2.java数组复制的3种方式和效率对比
*
* Created by 大屎蛋 on 2018/5/23.
*/
public class Demo1 {
public static void main(String[] args) {
/** 初始化数组*/
int len = 1000;
int count = 10000000;
int[] arr0 = new int[len];
for (int i = 0; i < len; i++) {
arr0[i] = i;
}
long t1 = System.currentTimeMillis();
for (int c = 0; c < count; c++) {
/** 1 for 循环复制*/
int[] arr1 = new int[len];
for (int i = 0; i < len; i++) {
arr1[i] = arr0[i];
}
}
long t2 = System.currentTimeMillis();
/** 2 Arrays.copyOf复制数组*/
for (int c = 0; c < count; c++) {
int[] arr2 = Arrays.copyOf(arr0, arr0.length);
}
long t3 = System.currentTimeMillis();
/** 3 System.arraycopy复制数组*/
for (int c = 0; c < count; c++) {
int[] arr3 = new int[len];
System.arraycopy(arr0, 0, arr3, 0, arr0.length);
}
long t4 = System.currentTimeMillis();
/** 4 Object.clone() 复制数组*/
for (int c = 0; c < count; c++) {
int[] arr4 = arr0.clone();
}
long t5 = System.currentTimeMillis();
System.out.println("1 for 循环复制: " + (t2 - t1));
System.out.println("2 Arrays.copyOf复制数组: " + (t3 - t2));
System.out.println("3 System.arraycopy复制数组: " + (t4 - t3));
System.out.println("4 Object.clone() 复制数组: * " + (t5 - t4));
}
}输出结果:
1 for 循环复制: 4451
2 Arrays.copyOf复制数组: 6474
3 System.arraycopy复制数组: 6439
4 Object.clone() 复制数组: * 6436这个输出结果根据电脑和运行环境,可能会不一致。从这个输出可以看出:
for循环遍历数组复制的方式用时最小.比其他3中少了50%左右的时间。
- 其他不变,只将循环次数改为一百万次的输出结果
1 for 循环复制: 640
2 Arrays.copyOf复制数组: 828
3 System.arraycopy复制数组: 643
4 Object.clone() 复制数组: * 645这个差距就很小了。
- 其他不变,循环次数改为一千万次的输出结果,初始数组的长度100的输出结果
1 for 循环复制: 948
2 Arrays.copyOf复制数组: 709
3 System.arraycopy复制数组: 659
4 Object.clone() 复制数组: * 666这个差距也不大。反而是for循环遍历耗时最多。
- 其他不变,循环次数改为一千万次的输出结果,初始数组的长度10的输出结果
1 for 循环复制: 250
2 Arrays.copyOf复制数组: 127
3 System.arraycopy复制数组: 157
4 Object.clone() 复制数组: * 193在数组长度为10的时候,for循环遍历赋值耗时要超过其他3种方式。
- 其他不变,循环次数改为一百万次,初始数组的长度10000的输出结果
1 for 循环复制: 5851
2 Arrays.copyOf复制数组: 6471
3 System.arraycopy复制数组: 6443
4 Object.clone() 复制数组: 6485这个输出结果差不多。
3 结论
通过上述测试代码的输出数据,可以简单分析一下,当数组长度超过一定值的时候(测试代码中,长度改为1000,这个值不精确),for循环遍历赋值,效率会略高出其他3种方式。
另外在运行次数长的时候(测试代码改为运行1千万次,数组长度1000)的时候,for循环遍历赋值效率最高,而且优势明显(快50%左右)。数组长度改为100,就没那么明显了。
System.arraycopy提供了截取数组中的一部分来生成新的数组,这个功能很方便。(也可以用for循环遍历来实现)。
Arrays.copyOf()和clone()方法可以复制整个数组,在数组长度比较短的时候,代码比较简介,推荐采用。