我知道常见的性能重构是用for
替换简单的System.arraycopy.
我想问一下:
system.arraycopy究竟何时开始有意义(考虑到它是本机方法调用)。复制小东西是否会说,< 32有什么优势?
这是我的印象,还是不能简单地用arraycopy复制(高效)这样的循环:
for (int j = 0; j < 2; ++j) {
vpr[m][s + j][i] = vr[j];
}
答案 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)
)进行了测试,得到了相同的结果。