如何编写Java for循环以避免重复计算上限

时间:2014-08-28 03:07:45

标签: java optimization jit

我一般写

for (int i = 0, n = someMethod(); i < n; i++)

优先于

for (int i = 0; i < someMethod(); i++)

避免重复计算someMethod()。但是,我真的不确定何时需要这样做。 Java在识别每次都会给出相同结果的方法时有多聪明,只需要在循环开始时执行一次?

2 个答案:

答案 0 :(得分:4)

我相信作为程序员,您有责任确定需要动态计算for-loop上限的情况,并相应地解决这些问题。

假设n的值不依赖于在循环中执行的某些操作,个人而言,我希望它写为

int n = someMethod();
for (int i = 0; i < n; i++);

因为它保留了最常见的for-loop样式,同时明确定义了上限。

答案 1 :(得分:1)

据我所知,JIT只会检测到它,如果它是一个相当简单的可内联方法。据说,程序员很容易检测到这些情况,这对于JIT编译器来说是一个难以检测的问题。您最好使用final int来缓存大型方法的结果,因为JIT可以非常轻松地检测到该值无法更改,甚至可以删除数组访问检查以加快循环。

这样的东西
int[] arr = new int[ 10 ];
for( int i = 0; i < arr.length; i++ ) {
    //...
}

List< String > list = Arrays.asList( new String[] { ... } );
for( int i = 0; i < list.size(); i++ ) {
    //...
}

可能很容易被JIT优化。调用大型或复杂方法的其他循环很容易被证明总是返回相同的值,但size()之类的方法可能内联甚至完全删除。

最后在数组上使用for-each循环。它们衰减到我在数组的情况下发布的第一个循环,并且还可以轻松地进行优化以产生最快的循环。虽然对于非阵列上的每个循环,我更喜欢避免快速循环,因为它们衰减到Iterator循环而不是我发布的第二个循环。对于LinkedList来说,情况并非如此,因为由于O(n)遍历,Iterator比使用get()更快。

这是关于JIT可以做什么来优化循环的所有猜测。重要的是要知道JIT只能优化它可以证明不会改变结果效果的东西。保持简单将使JIT的工作变得更加容易。喜欢使用final关键字。使用最终值或方法允许JIT轻松证明不会发生变化并且可以像疯了一样内联。这是JIT最重要的优化,内联。让这项工作变得轻松,JIT将帮助您大做出任何事情。

这是一个link讨论循环优化,如果JIT不能证明它的优化不会改变任何东西,那么JIT就不能总是优化循环。