关于循环有效工作的两个问题

时间:2015-08-21 16:58:55

标签: java performance

1。假设以下情况。

首先

int x;
for (int i = 0; i < MAX; i++){
    // some magic with x
    System.out.println(x);
}

第二

for (int i = 0; i < MAX; i++){
    int x;
    // some magic with x
    System.out.println(x);
}

那么哪一段代码更好,效率更高?

2。另外两种情况。

首先

int size = array.length;
for (int i = 0; i < size; i++) {
    // do something with array[i]
}

第二

for (int i = 0; i < array.length; i++) {
    // do something with array[i]
}

将数组长度保存到变量是否更有效?

2 个答案:

答案 0 :(得分:2)

length只是数组对象中的一个属性,它不需要任何时间来获取长度。

从变量读取相同,它不需要遍历整个数组来获取长度。

前两个只是范围。

本地 - 仅在循环内可用。

全球 - 可通过。

获取

假设你想要除以2时数字的余数。

for(int i = 0; i < 10; ++i)
{
 int remainder = i % 2;
 System.out.println(remainder);
}

并假设计算前10个自然数的总和。

int sum = 0;
for(int i = 0; i <= 10; ++i)
 {
    //declaring sum here doesnt make sense
     sum += i;
 } 
System.out.println(sum);//sum is available here.

PS:你可以只用n个自然数公式的总和。

答案 1 :(得分:1)

1。你应该更关心的是效率,而不是范围。通常,您应该尽可能地将变量保持为本地范围。这意味着,如果你只需要循环中的x,你应该在循环中定义它。

将变量保持为本地范围,您将获得许多好处:

  • 您的代码对其他人来说更具可读性
  • 您不会意外地分配或使用您仍在范围内的代码中进一步定义的变量的值,从而最大限度地减少程序中的错误
  • 最重要的是,垃圾收集器一旦超出范围就会释放变量使用的所有内存,从而保持程序性能高,内存使用率低。

您可以阅读更多关于Josh Bloch优秀书籍的变量范围和最佳实践,&#34; Effective Java&#34; (范围在第13和45项中讨论)。您可能还想阅读第55项,其中讨论了对optimize judiciously重要的原因。

2。对于问题的第二部分,请参阅Skeet的回答here

以下是一个例子:

public static void main(String[] args) {
    for(int i=0; i<getSize(); i++) {
        System.out.println("i: " + i);
    }
}

private static int getSize() {
    int size = new Random().nextInt(10);
    System.out.println("size: " + size);
    return size;
}

输出:

size: 2
i: 0
size: 4
i: 1
size: 4
i: 2
size: 8
i: 3
size: 0

注意如何为循环的每次迭代调用getSize()。在您的示例中,调用.length不会产生巨大的差异,因为JIT运行时将知道如何优化此调用。但是假设getSize()是一个更复杂的操作,比如计算数据库表中的行数。您的代码将非常慢,因为循环的每次迭代都将调用getSize(),从而导致数据库往返。

这是你最好先评估价值的时候。您可以执行此操作并仍保留size的最小范围,如下所示:

public static void main(String[] args) {
    for(int size = getSize(), i=0; i<size; i++) {
        System.out.println("i: " + i);
    }
}


private static int getSize() {
    int size = new Random().nextInt(10);
    System.out.println("size: " + size);
    return size;
}

size: 5
i: 0
i: 1
i: 2
i: 3
i: 4

注意getSize()仅被调用一次,而size变量仅在循环内可用,并在循环完成后立即超出范围。