阵列访问优化

Ljd*_*son 3 java arrays optimization android

我在Java中有一个10x10数组,数组中的一些项目没有使用,我需要遍历所有元素作为方法的一部分.什么会更好:

  1. 使用2 for循环遍历所有元素并检查nulltype以避免错误,例如

    for(int y=0;y<10;y++){
        for(int x=0;x<10;x++){
           if(array[x][y]!=null)
                //perform task here
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 或者更好地保留所有已使用地址的列表...说一个点的arraylist?

  3. 我没有提到的不同之处.

我期待任何答案:)

qua*_*dev 5

您尝试的任何解决方案都需要在尽可能类似生产条件的受控条件下进行测试.由于Java的本质,你需要稍微运用你的代码来获得可靠的性能统计数据,但我相信你已经知道了.

这就是说,你可以尝试一些事情,我用它来成功优化我的Java代码(但不是在Android JVM上)

for(int y=0;y<10;y++){
    for(int x=0;x<10;x++){
       if(array[x][y]!=null)
            //perform task here
    }
}
Run Code Online (Sandbox Code Playgroud)

在任何情况下都应该重新加工

for(int x=0;x<10;x++){
    for(int y=0;y<10;y++){
       if(array[x][y]!=null)
            //perform task here
    }
}
Run Code Online (Sandbox Code Playgroud)

通常,您可以通过缓存行引用来提高性能.假设数组的类型为Foo[][]:

for(int x=0;x<10;x++){
    final Foo[] row = array[x];
    for(int y=0;y<10;y++){
       if(row[y]!=null)
            //perform task here
    }
}
Run Code Online (Sandbox Code Playgroud)

使用final变量可以帮助JVM优化代码,但我认为现代JIT Java编译器在很多情况下可以自己弄清楚变量是否在代码中发生了变化.另一方面,有时候这可能会更有效率,尽管我们肯定会进入微观优化的领域:

Foo[] row;
for(int x=0;x<10;x++){
    row = array[x];
    for(int y=0;y<10;y++){
       if(row[y]!=null)
            //perform task here
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您不需要知道元素的索引以便对其执行任务,则可以将其写为

for(final Foo[] row: array){
    for(final Foo elem: row
       if(elem!=null)
            //perform task here
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以尝试的另一件事是展平数组并将元素存储在Foo[]数组中,以确保最大的引用局部性.你没有内心循环需要担心,但是在引用特定的数组元素时需要做一些索引算法(而不是在整个数组上循环).根据您的使用频率,它可能有益或无益.

由于大多数元素都不是null,因此将它们保存为稀疏数组对您没有好处,因为您丢失了引用的局部性.

另一个问题是空测试.null测试本身并不需要花费太多,但是跟随它的条件语句确实如此,因为你在代码中得到一个分支并且在错误的分支预测上浪费时间.你可以做的是使用一个"空对象",任务可以执行,但相当于非操作或同等良性.根据您要执行的任务,它可能适用于您,也可能不适合您.

希望这可以帮助.