我一直在重构一次性代码,这是我几年前以类似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的Java Generics语法和数字时,我有以下问题:
性能.该代码计划使用大约10 ^ 8 - 10 ^ 9秒/年,这几乎是可管理的.我的阅读建议将double变为Double有时可以在性能上增加3倍.我想要其他经验.我也希望从foo []移动到List也会受到影响.我没有第一手的知识,经验也很有用.
数组绑定检查.这在double []和List中有不同的处理方式吗?我期望一些问题违反界限,因为算法相当简单并且仅应用于少数数据集.
如果我不重构那么代码就有两种方法的丑陋且可能是脆弱的混合.我已经在尝试写下这样的东西:
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; } //... } }
我认为编译器在做这类事情时应该很聪明.我们还需要这样做吗?
I read an excellent book by Kent Beck on coding best-practices ( http://www.amazon.com/Implementation-Patterns/dp/B000XPRRVM ). There are also interesting performance figures. Specifically, there are comparison between arrays and various collections., and arrays are really much faster (maybe x3 compared to ArrayList).
Also, if you use Double instead of double, you need to stick to it, and use no double, as auto(un)boxing will kill your performance.
Considering your performance need, I would stick to array of primitive type.
Even more, I would calculate only once the upper bound for the condition in loops. This is typically done the line before the loop.
However, if you don't like that the upper bound variable, used only in the loop, is accessible outside the loop, you can take advantage of the initialization phase of the for loop like this:
for (int i=0, max=list.size(); i
I don't believe in obsolescence for arrays in java. For performance-critical loop, I can't see any language designer taking away the fastest option (especially if the difference is x3).
我理解您对可维护性的关注,以及与应用程序其余部分的一致性.但我认为关键循环有权采取一些特殊做法.
我会尝试在不改变代码的情况下使代码尽可能清晰:
通过仔细询问每个变量名称,理想情况下与我的同事进行10分钟的头脑风暴会议
通过编写编码注释(我反对它们的使用一般,因为不清楚的代码应该清楚,不要注释;但是一个关键的循环证明它是正确的).
根据需要使用私有方法(正如Andreas_D在他的回答中指出的那样).如果做了
private final
,很可能(因为它们会很短)它们在运行时会被内联,因此在运行时不会对性能产生影响.