任何你尝试的解决方案都需要在尽可能接近生产环境的受控条件下进行测试。由于Java的特性,你需要运行你的代码一段时间以获取可靠的性能统计数据,但我相信你已经知道了这一点。
话虽如此,还是有几个可以尝试的优化方法,我用过并且成功地优化了我的Java代码(但不适用于Android JVM)。
for(int y=0;y<10;y++){
for(int x=0;x<10;x++){
if(array[x][y]!=null)
}
}
应该在任何情况下重新制作
for(int x=0;x<10;x++){
for(int y=0;y<10;y++){
if(array[x][y]!=null)
}
}
通常,通过缓存行引用可以提高性能。假设数组的类型为Foo[][]
:
for(int x=0;x<10;x++){
final Foo[] row = array[x];
for(int y=0;y<10;y++){
if(row[y]!=null)
}
}
使用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)
}
}
如果您不需要知道元素的索引来执行任务,可以这样编写:
for(final Foo[] row: array){
for(final Foo elem: row
if(elem!=null)
}
}
另一种尝试是将数组展平并将元素存储在
Foo[]
数组中,确保最大的引用局部性。您无需担心内部循环,但在引用特定数组元素时需要进行一些索引算术运算(而不是循环整个数组)。根据您执行此操作的频率,它可能有益也可能没有益处。
由于大多数元素都不为空,将它们保留为稀疏数组对您没有好处,因为您会失去引用局部性。
另一个问题是空值测试。空值测试本身的成本不高,但其后面的条件语句成本很高,因为代码中会出现分支,并且在错误的分支预测上浪费时间。您可以使用“null 对象”,在此对象上执行任务将成为非操作或其他同样良性的操作。根据您要执行的任务,它可能有效也可能无效。
希望这有所帮助。