多维数组上的高效System.arraycopy

时间:2010-01-14 23:40:17

标签: java arrays

我知道常见的性能重构是用for替换简单的System.arraycopy.

我想问一下:

  1. system.arraycopy究竟何时开始有意义(考虑到它是本机方法调用)。复制小东西是否会说,< 32有什么优势?

  2. 这是我的印象,还是不能简单地用arraycopy复制(高效)这样的循环:

       for (int j = 0; j < 2; ++j) {
           vpr[m][s + j][i] = vr[j];
       }
    

5 个答案:

答案 0 :(得分:23)

使用System.arraycopy进行快速深层复制并不困难。以下是2D数组的示例:

for (int i = 0; i < src.length; i++) {
    System.arraycopy(src[i], 0, dest[i], 0, src[0].length);
}

从快速计时测试中,使用它来复制1000x1000 2D阵列100次需要40毫秒,相比之下1740毫秒使用更明显的两个for循环和分配。

答案 1 :(得分:8)

与所有性能计时问题一样,您确实需要在您希望运行代码的环境中进行基准测试。不同的JVM版本和硬件(CPU,内存等)配置可能会有不同的结果。这实际上取决于您的具体性能要求。

但是,在达到这种级别的性能调优之前,您应该首先清楚地编写代码并首先使其正确。编译器和JIT将能够使用常规算法表达式为您进行大量优化,但有时手动优化可能会混淆这些自动优化。在您拥有一个正在运行的产品之后,如果性能不是您想要的,那么只能分析和处理热点。 (虽然有时候对于更复杂的代码,您可能需要重构和/或更改逻辑。)

在这种情况下,如果您复制整个数组,则使用System.arraycopy,因为这是执行此操作的标准方法。编译器现在或将来可以为此提供额外的优化,因为核心API严重依赖于此,您可以放心,这是JVM开发人员一直希望以最佳方式运行的。

您需要运行一些循环,因为System.arraycopy只能执行单个数组对象,而Java多维数组实际上是数组数组。所以......

public int[][][] copyOf3Dim(int[][][] array) {
    int[][][] copy;
    copy = new int[array.length][][];
    for (int i = 0; i < array.length; i++) {
        copy[i] = new int[array[i].length][];
        for (int j = 0; j < array[i].length; j++) {
            copy[i][j] = new int[array[i][j].length];
            System.arraycopy(array[i][j], 0, copy[i][j], 0, 
                array[i][j].length);
        }
    }
    return copy;
}    

或者您可以使用Arrays.copyOf使用System.arraycopy并在内部进行一些反射(因此速度不如直接使用System.arraycopy),但不会进行深层复制。

答案 2 :(得分:3)

System.arrayCopy可能是复制数组的最快方法,但它不会制作深层副本。

在第二个问题中,它也无法做更复杂的例子。

答案 3 :(得分:1)

AFAIK,System.arrayCopy是复制阵列的最有效和最佳方式。我不知道任何情况下,实现自己的循环的替代方法对于直接复制更有效。

答案 4 :(得分:0)

在我的用例中

public <T> T[][] arrayCopy(T[][] array) {

    return Arrays.stream(array).
              map(el -> el.clone()).toArray(a -> array.clone());
}

方式比使用System.arraycopy或直接的两个for循环解决方案更快。
还使用原语(arrayCopy(int[][] array))进行了测试,得到了相同的结果。