【发布时间】:2010-11-27 10:08:31
【问题描述】:
我一直在重构我几年前以类似 FORTRAN 的风格编写的一次性代码。现在大部分代码都更有条理和可读性。然而,算法的核心(对性能至关重要)使用 1 维和 2 维 Java 数组,其典型代表是:
for (int j = 1; j < len[1]+1; j++) {
int jj = (cont == BY_TYPE) ? seq[1][j-1] : j-1;
for (int i = 1; i < len[0]+1; i++) {
matrix[i][j] = matrix[i-1][j] + gap;
double m = matrix[i][j-1] + gap;
if (m > matrix[i][j]) {
matrix[i][j] = m;
pointers[i][j] = UP;
}
//...
}
}
为了清晰、可维护性和与其余代码的交互,我想对其进行重构。但是在阅读Java Generics Syntax for arrays 和Java Generics and numbers 时,我有以下担忧:
性能。该代码计划使用大约 10^8 - 10^9 秒/年,这几乎是可管理的。我的阅读表明,将 double 更改为 Double 有时可以将性能提高 3 倍。我想要这方面的其他经验。我还希望从 foo[] 移动到 List 也会很受欢迎。我没有第一手的知识,再次经验会很有用。
数组绑定检查。这在 double[] 和 List 中的处理方式不同吗?这有关系吗?我预计一些问题会超出界限,因为该算法相当简单并且只应用于少数数据集。
-
如果我不重构,那么代码就会有两种方法的丑陋且可能很脆弱的混合。我已经在尝试编写如下内容:
列表
和 列表[]
并了解擦除不会使这变得漂亮,并且充其量会引起编译器警告。如果没有非常复杂的结构,似乎很难做到这一点。
- 已过时。一位发帖人建议应该废弃 Java 数组。我认为这不会发生 RSN,但我想摆脱过时的方法。
总结到目前为止的共识:
集合对原始数组的性能有显着影响,尤其是对于矩阵等构造。这是在自动(取消)装箱数字和访问列表项时发生的
对于严格的数值(科学)算法,数组表示法 [][] 实际上更易于阅读,但变量的命名应尽可能有用
泛型和数组不能很好地混合。将数组包装在类中以将它们传入/传出紧密算法可能很有用。
几乎没有客观的理由做出改变
问题 @SeanOwen 建议从循环中取出常量值会很有用。假设我没有搞砸这看起来像:
int len1 = len[1];
int len0 = len[0];
int seq1 = seq[1];
int[] pointersi;
double[] matrixi;
for (int i = 1; i < len0+1; i++) {
matrixi = matrix[i];
pointersi = pointers[i];
}
for (int j = 1; j < len1+1; j++) {
int jj = (cont == BY_TYPE) ? seq1[j-1] : j-1;
for (int i = 1; i < len0+1; i++) {
matrixi[j] = matrixi[j] + gap;
double m = matrixi[j-1] + gap;
if (m > matrixi[j]) {
matrixi[j] = m;
pointersi[j] = UP;
}
//...
}
}
我认为编译器在做这类事情时应该很聪明。我们还需要这样做吗?
【问题讨论】:
-
+1 表示引起极大兴趣的问题
标签: java arrays generics collections