Efficiency of method call in for loop condition

为君一笑 提交于 2019-11-30 13:11:11

By specification, the idiom

for (String extension : assetLoader.getSupportedExtensions()) {
  ...
}

expands into

for (Iterator<String> it = assetLoader.getSupportedExtensions().iterator(); it.hasNext();)
{
    String extension = it.next();
    ...
}

Therefore the call you ask about occurs only once, at loop init time. It is the iterator object whose methods are being called repeatedly.

However, if you are honestly interested about the performance of your application, then you should make sure you're focusing on the big wins and not small potatoes like this. It is almost impossible to make a getter call stand out as a bottleneck in any piece of code. This goes double for applications running on HotSpot, which will inline that getter call and turn it into a direct field access.

No, the method assetLoader.getSupportedExtensions() is called only once before the first iteration of the loop, and is used to create an Iterator<String> used by the enhanced for loop.

The two snippets will have the same performance.

  1. Direct cost.

Since, as people said before, the following

for (String extension : assetLoader.getSupportedExtensions()) {
  //stuff
}

transforms into

for (Iterator<String> it = assetLoader.getSupportedExtensions().iterator(); it.hasNext();) {
    String extension = it.next();
    //stuf
}

getSupportedExtensions() is called once and both of your code snippets have the same performance cost, but not the best performance possible to go through the List, because of...

  1. Indirect cost

Which is the cost of instantiation and utilization of new short-living object + cost of method next(). Method iterator() prepares an instance of Iterator. So, it is need to spend time to instantiate the object and then (when that object becomes unreachable) to GC it. The total indirect cost isn't so much (about 10 instructions to allocate memory for new object + a few instructions of constructor + about 5 lines of ArrayList.Itr.next() + removing of the object from Eden on minor GC), but I personally prefer indexing (or even plain arrays):

ArrayList<String> supportedExtensions = ((IAssetLoader<?>) loader).getSupportedExtensions();

for (int i = 0; i < supportedExtensions.size(); i++) {
    String extension = supportedExtensions.get(i);
    // stuff
}

over iterating when I have to iterate through the list frequently in the main path of my application. Some other examples of standard java code with hidden cost are some String methods (substring(), trim() etc.), NIO Selectors, boxing/unboxing of primitives to store them in Collections etc.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!