全部,
在浏览 Java API 中的一些文件时,我注意到许多循环计数器正在递减而不是递增的实例。即在 for
和 while
循环中 String类(class)。尽管这可能微不足道,但递减计数器而不是递增计数器有什么意义吗?
最佳答案
我用 eclipse 3.6 (java 6) 编译了两个简单的循环,并查看了字节码是否存在一些差异。这是代码:
for(int i = 2; i >= 0; i--){}
for(int i = 0; i <= 2; i++){}
这是字节码:
// 1st for loop - decrement 2 -> 0
0 iconst_2
1 istore_1 // i:=2
2 goto 8
5 inc 1 -1 // i+=(-1)
8 iload_1
9 ifge 5 // if (i >= 0) goto 5
// 2nd for loop - increment 0 -> 2
12 iconst_0
13 istore_1 // i:=0
14 goto 20
17 inc 1 1 // i+=1
20 iload_1
21 iconst 2
22 if_icmple 17 // if (i <= 2) goto 17
递增/递减操作应该没有区别,它要么是+1
,要么是+(-1)
。这个典型 (!) 示例的主要区别在于,在第一个示例中我们比较 0 (ifge i
),在第二个示例中我们比较一个值 (if_icmple i 2
)。并且在每次迭代中完成比较。因此,如果有任何(轻微的)性能提升,我认为这是因为与 0 比较比与其他值比较成本更低。所以我想造成差异的不是递增/递减,而是停止条件。
因此,如果您需要在源代码级别进行一些微优化,请尝试以与零比较的方式编写循环,否则请尽可能保持可读性(递增更容易理解):
for (int i = 0; i <= 2; i++) {} // readable
for (int i = -2; i <= 0; i++) {} // micro-optimized and "faster" (hopefully)
添加
昨天我做了一个非常基本的测试 - 刚刚创建了一个 2000x2000 数组并根据单元格索引的计算填充单元格,一次从 0->1999
开始计算行和单元格,另一次从 1999->0
开始倒退。我对这两种情况具有相似的性能(在我的机器上为 185..210 毫秒)并不感到惊讶。
所以是的,在字节码级别(eclipse 3.6)上存在差异,但是,嘿,我们现在是 2010 年,现在似乎没有什么显着差异。因此,再次使用 Stephens 的话来说,“不要在这种优化上浪费你的时间”。保持代码的可读性和可理解性。
关于java - Java API 中的循环计数器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4181941/