为什么 clone() 是复制数组的最佳方式?

2022-09-01 06:53:14

这对我来说很可惜,但我不知道:

您应该使用克隆来复制阵列,因为这通常是最快的方法。

正如Josh Bloch在这篇博客中所说:http://www.artima.com/intv/bloch13.html

我总是使用.这两种方法都是原生的,所以可能没有深入研究库的来源,我无法弄清楚为什么会这样。System.arraycopy(...)

我的问题很简单:为什么它是最快的方法?System.arraycopy 有什么区别?这里解释了差异,但它没有回答为什么Josh Bloch认为是最快的方法的问题。clone()


答案 1

我想提出一些关于为什么复制数组的最快方法比其他方法更重要的观点:clone()System.arraycopy(..)

1. 在将源数组复制到目标数组之前,不必执行类型检查,如此处所示。它只是简单地分配新的内存空间并将对象分配给它。另一方面,检查类型,然后复制数组。clone()System.arraycopy(..)

2.还打破了优化,消除了冗余归零。如您所知,Java中每个分配的数组都必须使用或相应的缺省值进行初始化。但是,如果 JIT 在创建后立即看到数组已填充,则可以避免将此数组清零。与使用现有或相应的默认值更改复制值相比,这无疑更快。使用 时花费大量时间清除和复制初始化的数组。为此,我执行了一些基准测试。clone()0s0sSystem.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

根据我得到的输出,几乎是两倍快cloneSystem.arraycopy(..)

3.此外,使用手动复制方法(如结果)到更快的输出中,因为它不必进行任何VM调用(与)。clone()System.arraycopy()


答案 2

首先,不必进行类型检查。clone()System.arraycopy()