例如:
for(int i = 0; i < 20 * 40 * 60 * 80; i++){ ... }
与:相比:
for(int i = 0; i < 3840000; i++){ ... }
第一个循环比第二个循环慢得多(做了一些时间试验),即使条件的值在整个迭代的任何阶段都不会改变。当然,使用方法会有所不同,因为该值可能会发生变化(即使它可能不应该)。我只是想知道为什么Java不会缓存/临时该值。
long fact10 = factorial(10);
for(long n = 0; n < fact10; n++) vs for(long n = 0; n < factorial(10); n++)
答案 0 :(得分:6)
Java无法进行第二次优化,因为它不知道factorial
没有副作用。就第一个基准测试而言,我确信这是某种错误:Java编译器在编译时计算常量表达式的结果,因此前两个循环是等效的。
答案 1 :(得分:2)
我认为你的微基准是有缺陷的,大多数是。
正确的基准测试是一种艺术形式。 Oracle JVM有一个即时编译器(JIT),我相信如果你运行这么长时间,你会看到它最终加速,因为他们试图推断这些值永远不会改变。
答案 2 :(得分:0)
理论上(尽管我在这方面取得了不好的成绩),你可以改变你的“&lt;”的结果。循环中的陈述。
例如:
int x = 1;
for(int i = 0; i < x * 2; i++)
{
if(x < 10)
x += i;
}
我不知道为什么每次都进行计算的确切原因,无论值如何,但在每次迭代过程中,如果存在变量,它总是重新计算数学。
答案 3 :(得分:0)
我认为没关系,每次都会检查这个条件。所以你可以实现这样的东西:
synchronized (veryBigList) {
for (Iterator iter = veryBigList.iterator();iter.hasNext();) {
Object o = iter.next();
//Do something
}
}
请注意,某些列表实现具有不同的性能。 我想(现在不确定),
ArrayList 在size()
上速度非常快,但在add()
上速度很慢
底层阵列必须扩展。 LinkedList 在size()
上很慢,
但在add()
我更喜欢这个解决方案:
synchronized (veryBigList) {
for (int i = 0, l = veryBigList.size(); i < l; i++) {
//Do something
}
}
答案 4 :(得分:0)
自从我编写了一个小程序以来,你在循环中所拥有的内容在两种情况下所用的时间几乎相同。所以它真的取决于你在第一和第二循环中的内容。
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
int x = 0;
for (int i = 0; i < 500000000 ; i++) {
x++;
}
long endTime = System.currentTimeMillis();
long totalTime1 = endTime - startTime;
System.out.println("First time " + totalTime1);
startTime = System.currentTimeMillis();
int j = 0;
for (int i = 0; i < 50 * 100 * 10 * 10000 ; i++) {
j++;
}
endTime = System.currentTimeMillis();
long totalTime2 = endTime - startTime;
System.out.println("Second time " + totalTime2);
System.out.println( "First Loop " + totalTime1 + " Second Loop " + totalTime2 );
}