循环条件下方法调用的java效率
我正在编写一个游戏引擎,其中ArrayList
中的一组对象使用for循环进行迭代。显然,效率非常重要,所以我想知道循环的效率
for (String extension : assetLoader.getSupportedExtensions()) {
// do stuff with the extension here
}
其中getSupportedExtension()
返回ArrayList
{ArrayList
。我想知道的是,是否每次循环迭代新扩展时都调用该方法。如果是这样的话,采取以下措施是否更有效:
ArrayList<String> supportedExtensions = ((IAssetLoader<?>) loader).getSupportedExtensions();
for (String extension : supportedExtensions) {
// stuff
}
??提前谢谢
# 1 楼答案
否,方法
assetLoader.getSupportedExtensions()
在循环的第一次迭代之前只调用一次,用于创建增强for循环使用的Iterator<String>
这两个代码段将具有相同的性能
# 2 楼答案
根据规范,成语
扩展到
因此,您询问的呼叫仅在循环初始时间发生一次。它是迭代器对象,其方法被反复调用
然而,如果你真的对你的应用程序的性能感兴趣,那么你应该确保你关注的是大的胜利,而不是像这样的小人物。在任何一段代码中,让getter调用成为瓶颈几乎是不可能的。对于运行在HotSpot上的应用程序,这将内联getter调用,并将其转换为直接字段访问
# 3 楼答案
正如人们之前所说,因为
转化为
getSupportedExtensions()只调用一次,并且两个代码段的性能成本相同,但由于
这是实例化和使用新的短期对象的成本+方法next()的成本。方法iterator()准备迭代器的实例。因此,需要花时间实例化对象,然后(当对象变得不可访问时)对其进行GC。总的间接成本不算太高(大约10条为新对象分配内存的指令+一些构造函数指令+大约5行ArrayList.Itr.next()+在次要GC上从Eden删除对象),但我个人更喜欢索引(甚至是普通数组):
当我必须在应用程序的主路径中频繁地遍历列表时,进行迭代。具有隐藏成本的标准java代码的其他一些示例包括一些字符串方法(substring()、trim()等)、NIO选择器、将原语装箱/拆箱以将其存储在集合中等