当前位置: 首页 > 面试题库 >

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

梁盛
2023-03-14
问题内容

这对我来说是一个耻辱,但我不知道:

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

如Josh Bloch在此博客中所述:http :
//www.artima.com/intv/bloch13.html

我一直都习惯System.arraycopy(...)。两种方法都是本机的,所以可能没有深入研究我不知道的库来源,为什么会这样。

我的问题很简单:为什么这是 最快的 方法?
有什么区别 System.arraycopy此处
说明了差异,但未回答为何乔什·布洛赫(JoshBloch)认为clone()这是最快的方法。


问题答案:

我想就为什么clone()复制数组比System.arraycopy(..)其他方法最快的方法提出一些意见:

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

2.
clone()还破坏了消除冗余归零的优化。如您所知,Java中每个分配的数组都必须使用0s或各自的默认值进行初始化。但是,如果JIT看到该数组在创建后立即被填充,则可以避免将该数组清零。与使用现有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.
此外,clone()由于不需要进行任何VM调用(与一样System.arraycopy()),因此使用手动复制方法(如结果)到更快的输出中。



 类似资料:
  • 问题内容: 复制列表的最佳方法是什么?我知道以下方法,哪种更好?还是有另一种方法? 问题答案: 如果要浅拷贝(不复制元素),请使用: 如果要进行深层复制,请使用复制模块:

  • 问题内容: 我遇到了一个问题,需要成对地遍历数组。最好的方法是什么?或者,作为替代方案,将Array转换为成对的Array(然后可以正常迭代)的最佳方法是什么? 这是我得到的最好的。它必须是,而且不是很漂亮。有没有更好的办法? 问题答案: 您可以 映射 跨步而不是对其进行迭代,从而可以将结果作为 常量获取: 如果只需要遍历对,并且给定的数组很大,那么避免创建带有延迟映射的中间数组可能是有利的:

  • 问题内容: 在Clojure中制作 GUI的最佳方法是什么? 有一些功能性Swing或SWT包装器的示例吗?还是与JavaFX声明性GUI描述进行了某些集成,可以使用某些宏轻松地将它们包装到s表达式中? 有教程吗? 问题答案: 我会谦虚地建议跷跷板。 这是一个基于REPL的教程,假定您没有Java或Swing知识。 跷跷板很像@tomjen的建议。这是“你好,世界”: 这是@Abhijith和@d

  • 问题内容: 我使用带有文本区域(JTextArea)的Swing创建了一个应用程序。我想创建一个“编辑”菜单,其中包含从文本区域剪切和复制文本,以及将剪贴板中的文本粘贴到文本区域的选项。 我已经看到了几种方法来做到这一点,但是我想知道最好的方法是什么。我应该如何执行剪切/复制/粘贴? 问题答案: 我个人会选择重复使用标准的剪切,复制和粘贴操作。在Swing拖放教程中对此进行了说明:添加剪切,复制和

  • 问题内容: 我有一个状态数组,比方说this.state.arr。我想向此状态属性添加一些内容,然后更改更多属性。 选项1 选项2 所以..我知道this.state应该被视为不可变的。但是可以像在选项1中那样使用它还是可以通过它设置状态,还是可以像在选项2中那样使用它,这样总是总是首先在内存中进行复制 问题答案: 使用concat的另一种简单方法:

  • 问题内容: 为一个类获取类文字很容易: 但是,如何获取数组类型的类对象? 这可行,但是很丑陋,可能不是编译时间常数: 我查看了JLS,但唯一发现的是,根据JLS的定义,我所谓的“类文字”不是“文字”。 问题答案: 即使对于数组类型,您仍然可以使用类文字。这样编译就可以了。 JLS的15.8.2节规定: 甲 类文字 是由类,接口,的名称的表达 阵列 ,或原语类型或伪类型,接着是“” 和令牌。 (加粗