3

可能重复:
for循环优化

在java中我有一段代码:

List e = {element1, element2, ...., elementn};
for(int i = 0; i < e.size(); i++){//Do something in here
};

和另一个块:

List e = {element1, element2, ...., elementn};
int listSize = e.size();
for(int i = 0; i < listSize; i++){//Do something in here
};

我认为第二个块更好,因为在第一个块中, i​​f i++,我们必须再计算e.size()一次来比较for循环中的条件。是对还是错?比较上面的两个块,写作的最佳实践是什么?为什么?解释清楚并自己尝试这个循环

4

12 回答 12

14

我个人会改用增强的 for 语句:

for (Object element : e) {
    // Use element
}

当然,除非你需要索引。

如果我必须使用这两种形式中的一种,我会使用第一种,因为它更整洁(它不会引入另一个仅在该循环中使用的局部变量),直到我有具体证据表明它导致了问题。(在大多数列表实现中,e.size()是一个简单的变量访问,无论如何都可以由 JIT 内联。)

于 2012-05-11T08:25:44.150 回答
6

通常,最简短和可读的代码是最好的选择,一切都是平等的。在 Java 的情况下,增强的 for 循环(适用于任何实现 的类Iterable)是要走的路。

for (Object object : someCollection) { // do something }

仅就您发布的两个而言,我认为第一个是更好的选择。它更具可读性,并且您必须记住,在底层,JIT 将尝试优化您编写的大量代码。

编辑:你听说过“过早的优化是万恶之源”这句话吗?你的第二个块是过早优化的一个例子。

于 2012-05-11T08:24:52.977 回答
4

我会一直使用(如果你需要一个索引变量):

List e = {element1, element2, ...., elementn};
for(int i = 0, size = e.size(); i < size; i++){
    // Do something in here
};

因为e.size()可能是一项昂贵的操作。

您的第二个选项不好,因为它在for循环之外引入了一个新变量。我建议尽可能限制可变可见性。

否则一个

for (MyClass myObj : list) {
    // Do something here
}

更干净,但可能会带来小的性能损失(索引方法不需要实例化Iterator)。

于 2012-05-11T08:25:29.560 回答
4

如果您检查一个LinkedList类的 size() 实现,您会发现当从列表中添加或删除元素时,大小会增加或减少。调用size()只是返回这个属性的值,不涉及任何计算。
因此,直接调用 size() 方法应该会更好,因为您将保存另一个整数。

于 2012-05-11T08:26:45.110 回答
2

size()是的,由于您不重复执行方法调用,因此第二种形式的效率略高。编译器很好地自己进行这种优化。

但是,这不太可能成为应用程序的性能瓶颈。 避免过早优化。最重要的是使您的代码干净易读。

于 2012-05-11T08:24:53.740 回答
1

第二个是更好的方法,因为在第一个块中,您调用的e.size()是一个方法,它是循环中的一个操作,对 JVM 来说是一个额外的负担。

于 2012-05-11T08:24:49.963 回答
1

在大多数情况下,HotSpot 会将 e.size() 从循环中移出。所以它只会计算一次 List 的大小。

至于我,我更喜欢以下符号:

for (Object elem: e) {
   //Do something
}
于 2012-05-11T08:25:45.067 回答
1

我认为这应该更好..可能每次都初始化 int 变量可以从中逃脱..

List e = {element1, element2, ...., elementn};
int listSize = e.size();
int i=0;
for(i = 0; i < listSize; i++){//Do something in here
};
于 2012-05-11T08:26:24.400 回答
0

我不太确定,但我认为 java 的优化器会用静态值替换该值,所以最终它会是相同的。

于 2012-05-11T08:24:36.757 回答
0

为避免在编写代码时进行所有这些编号、迭代器和检查,请使用以下最简单易读的代码,该代码具有最大的性能。为什么这具有最佳性能(详细信息即将发布)

for (Object object : aCollection) { 
// Do something here
}

如果需要索引,那么:
在上述两种形式之间进行选择:
第二种更好,因为它只计算了一次大小。

于 2012-05-11T08:29:16.273 回答
0

我认为现在我们倾向于编写简短易懂的代码,所以第一个选项更好。

于 2012-05-11T08:31:08.933 回答
-1

第二个更好,因为在它的body中的第一个循环中可能你会做这个语句e.remove,然后e的大小会改变,所以最好在循环之前将大小保存在一个参数中

于 2012-05-11T08:23:53.483 回答