java中<Array Name> .length的时间复杂度或隐藏成本

Try*_*ing 12 java arrays complexity-theory

我在java中查看一个项目,发现一个for循环,如下所示:

for(int i=1; i<a.length; i++)
{
    ...........
    ...........
    ...........
}
Run Code Online (Sandbox Code Playgroud)

我的问题是:计算a.length(这里是数组名称)是否代价高昂?如果没有那么如何a.length在内部计算(意味着JVM如何确保O(1)访问它)?是类似于:

int length = a.length;
for(int i=1; i<length; i++)
{
    ...........
    ...........
    ...........
}
Run Code Online (Sandbox Code Playgroud)

就像访问函数内部的局部变量值一样.谢谢.

Jon*_*eet 15

我的问题是:计算a.length是否代价高昂

不.它只是阵列上的一个字段(参见JLS第10.7节).它并不昂贵,JVM知道它永远不会改变并且可以适当地优化循环.(实际上,我希望一个好的JIT能够注意到用非负数初始化变量的正常模式,检查它是否小于length然后访问数组 - 如果它注意到,它可以删除数组边界检查.)


ass*_*ias 9

a.length不是计算,而只是访问阵列中保存的字段.这种类型的读操作非常快.

如果代码是经常被调用的方法的一部分,那么几乎可以肯定JIT编译器会进行您建议的优化,以使其更快.

潜在的速度差在这里是纳秒(可能没有"s").

  • 通过`jmh` :)运行它 (2认同)
  • 我已经运行了,你的估计几乎是正确的:它是*带*"s",即*零纳秒*:) (2认同)

Mar*_*nik 5

为了您的方便,我对其进行了微基准测试。代码:

public class ArrayLength
{
  static final boolean[] ary = new boolean[10_000_000];
  static final Random rnd = new Random();
  @GenerateMicroBenchmark public void everyTime() {
    int sum = rnd.nextInt();
    for (int i = 0; i < ary.length; i++) sum += sum;
  }
  @GenerateMicroBenchmark public void justOnce() {
    int sum = rnd.nextInt();
    final int length = ary.length;
    for (int i = 0; i < length; i++) sum += sum;
  }
}
Run Code Online (Sandbox Code Playgroud)

结果:

Benchmark                     Mode Thr    Cnt  Sec         Mean   Mean error    Units
o.s.ArrayLength.everyTime    thrpt   1      3    5    40215.790     1490.800 ops/msec
o.s.ArrayLength.justOnce     thrpt   1      3    5    40231.192      966.007 ops/msec
Run Code Online (Sandbox Code Playgroud)

摘要:没有可检测到的变化。