我想提出一些关于为什么复制数组的最快方法比其他方法更重要的观点:clone()
System.arraycopy(..)
1. 在将源数组复制到目标数组之前,不必执行类型检查,如此处所示。它只是简单地分配新的内存空间并将对象分配给它。另一方面,检查类型,然后复制数组。clone()
System.arraycopy(..)
2.还打破了优化,消除了冗余归零。如您所知,Java中每个分配的数组都必须使用或相应的缺省值进行初始化。但是,如果 JIT 在创建后立即看到数组已填充,则可以避免将此数组清零。与使用现有或相应的默认值更改复制值相比,这无疑更快。使用 时花费大量时间清除和复制初始化的数组。为此,我执行了一些基准测试。clone()
0s
0s
System.arraycopy(..)
@BenchmarkMode(Mode.Throughput)
@Fork(1)
@State(Scope.Thread)
@Warmup(iterations = 10, time = 1, batchSize = 1000)
@Measurement(iterations = 10, time = 1, batchSize = 1000)
public class BenchmarkTests {
@Param({"1000","100","10","5", "1"})
private int size;
private int[] original;
@Setup
public void setup() {
original = new int[size];
for (int i = 0; i < size; i++) {
original[i] = i;
}
}
@Benchmark
public int[] SystemArrayCopy() {
final int length = size;
int[] destination = new int[length];
System.arraycopy(original, 0, destination, 0, length);
return destination;
}
@Benchmark
public int[] arrayClone() {
return original.clone();
}
}
输出:
Benchmark (size) Mode Cnt Score Error Units
ArrayCopy.SystemArrayCopy 1 thrpt 10 26324.251 ± 1532.265 ops/s
ArrayCopy.SystemArrayCopy 5 thrpt 10 26435.562 ± 2537.114 ops/s
ArrayCopy.SystemArrayCopy 10 thrpt 10 27262.200 ± 2145.334 ops/s
ArrayCopy.SystemArrayCopy 100 thrpt 10 10524.117 ± 474.325 ops/s
ArrayCopy.SystemArrayCopy 1000 thrpt 10 984.213 ± 121.934 ops/s
ArrayCopy.arrayClone 1 thrpt 10 55832.672 ± 4521.112 ops/s
ArrayCopy.arrayClone 5 thrpt 10 48174.496 ± 2728.928 ops/s
ArrayCopy.arrayClone 10 thrpt 10 46267.482 ± 4641.747 ops/s
ArrayCopy.arrayClone 100 thrpt 10 19837.480 ± 364.156 ops/s
ArrayCopy.arrayClone 1000 thrpt 10 1841.145 ± 110.322 ops/s
根据我得到的输出,几乎是两倍快clone
System.arraycopy(..)
3.此外,使用手动复制方法(如结果)到更快的输出中,因为它不必进行任何VM调用(与)。clone()
System.arraycopy()