对这个问题还是比较感兴趣的,为此我也写了一个测试。
package test;
import java.util.Arrays;
public class Main {
public static int[] testSystemArrayCopy(int[] orginal) {
int[] target = new int[orginal.length];
System.arraycopy(orginal, 0, target, 0, target.length);
return target;
}
public static int[] testArraysCopyOf(int[] orginal) {
int[] target = Arrays.copyOf(orginal, orginal.length);
return target;
}
public static int[] testClone(int[] orginal) {
int[] target = orginal.clone();
return target;
}
public static int[] testFor(int[] orginal) {
int[] target = new int[orginal.length];
for (int i = 0; i < orginal.length; i++) {
target[i] = orginal[i];
}
return target;
}
public static void main(String args[]) {
final int LEN = 10_000;
final int TIMES = 100_000;
int[] original = new int[LEN];
for (int i = 0; i < original.length; i++) {
original[i] = i;
}
System.out.println("Size of arrays: " + LEN);
// // heat up
// testArraysCopyOf(original);
// testSystemArrayCopy(original);
// testClone(original);
// testFor(original);
long startTime, endTime;
long totalSize = 0L;
startTime = System.nanoTime();
for (int i = 0; i < TIMES; i++) {
int[] target = testFor(original);
totalSize += target.length;
target = null;
}
endTime = System.nanoTime();
System.out.println("for loop: " + (endTime - startTime) / 1_000_000 + "ms");
// startTime = System.nanoTime();
// for (int i = 0; i < TIMES; i++) {
// int[] target = testSystemArrayCopy(original);
// totalSize += target.length;
// target = null;
// }
// endTime = System.nanoTime();
// System.out.println("System.arrayCopy(): " + (endTime - startTime) / 1_000_000 + "ms");
// startTime = System.nanoTime();
// for (int i = 0; i < TIMES; i++) {
// int[] target = testArraysCopyOf(original);
// totalSize += target.length;
// target = null;
// }
// endTime = System.nanoTime();
// System.out.println("Arrays.copyOf(): " + (endTime - startTime) / 1_000_000 + "ms");
// startTime = System.nanoTime();
// for (int i = 0; i < TIMES; i++) {
// int[] target = testClone(original);
// totalSize += target.length;
// target = null;
// }
// endTime = System.nanoTime();
// System.out.println("clone(): " + (endTime - startTime) / 1_000_000 + "ms");
System.out.println("total size: " + totalSize);
}
}
测试是在我的个人电脑上完成的,操作系统是 Windows 10, Java 版本 1.8。
每轮测试只执行一种方法,预热环节被我删了,因为现在每轮里面会执行多次,预热对结果的影响应该很小。当然,加上也是可以的。
再来说说测试时使用的参数。我使用的是下面的参数来运行的:
-Xms2g -Xmx2g -Xmn1g
初始和最大内存都是 2GB,这样可以最大程度减小 JVM 扩展堆时的开销。
每个用例(指不同的数组规模)都执行两轮,先按照正序执行一轮,再逆序执行一轮。
下面是整理后的结果:
Size of arrays: 10,000 (100k times)
# 1st
for loop: 592ms
System.arrayCopy(): 636ms
Arrays.copyOf(): 633ms
clone(): 681ms
# 2nd
for loop: 587ms
System.arrayCopy(): 622ms
Arrays.copyOf(): 628ms
clone(): 674ms
Size of arrays: 100,000 (10k times)
# 1st
for loop: 828ms
System.arrayCopy(): 849ms
Arrays.copyOf(): 801ms
clone(): 855ms
# 2nd
for loop: 821ms
System.arrayCopy(): 825ms
Arrays.copyOf(): 804ms
clone(): 874ms
Size of arrays: 1,000,000 (10k times)
# 1st
for loop: 7896ms
System.arrayCopy(): 9454ms
Arrays.copyOf(): 10362ms
clone(): 6934ms
# 2nd
for loop: 6789ms
System.arrayCopy(): 9318ms
Arrays.copyOf(): 9521ms
clone(): 6909ms
Size of arrays: 10,000,000 (1k times)
# 1st
for loop: 7697ms
System.arrayCopy(): 9236ms
Arrays.copyOf(): 9242ms
clone(): 8396ms
# 2nd
for loop: 7926ms
System.arrayCopy(): 9303ms
Arrays.copyOf(): 9203ms
clone(): 8500ms
Size of arrays: 100,000,000 (100 times)
# 1st
for loop: 7780ms
System.arrayCopy(): 8817ms
Arrays.copyOf(): 8886ms
clone(): 8808ms
# 2nd
for loop: 7772ms
System.arrayCopy(): 8818ms
Arrays.copyOf(): 9204ms
clone(): 9088ms
根据结果绘制的图表:
结论基本与楼主的差不多,怎么看都是 for 循环和 clone 比较快。
但是不太清楚为什么与楼上用 jmh 测试的结果差别这么大。但是如果让我选,我还是比较愿意相信我自己实际运行后得出的结论,因为使用测试工具,我也不知道它内部是如何完成测试的。