Java:通过HashMap迭代,哪个更高效?

新手上路,请多包涵

给定以下代码,有两种替代方法来遍历它,

这两种方法之间有什么性能差异吗?

         Map<String, Integer> map = new HashMap<String, Integer>();
        //populate map

        //alt. #1
        for (String key : map.keySet())
        {
            Integer value = map.get(key);
            //use key and value
        }

        //alt. #2
        for (Map.Entry<String, Integer> entry : map.entrySet())
        {
            String key = entry.getKey();
            Integer value = entry.getValue();
            //use key and value
        }

我倾向于认为 alt. #2 是遍历整个 map 的更有效方法(但我可能错了)

原文由 bguiz 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 482
2 个回答

您的第二个选项肯定更有效,因为与第一个选项中的 n 次相比,您只进行一次查找。

但是,没有什么比在可能的时候尝试一下更好的了。所以这里去 -

(不完美但足以验证假设并且无论如何在我的机器上)

 public static void main(String args[]) {

    Map<String, Integer> map = new HashMap<String, Integer>();
    // populate map

    int mapSize = 500000;
    int strLength = 5;
    for(int i=0;i<mapSize;i++)
        map.put(RandomStringUtils.random(strLength), RandomUtils.nextInt());

    long start = System.currentTimeMillis();
    // alt. #1
    for (String key : map.keySet()) {
        Integer value = map.get(key);
        // use key and value
    }
    System.out.println("Alt #1 took "+(System.currentTimeMillis()-start)+" ms");

    start = System.currentTimeMillis();
    // alt. #2
    for (Map.Entry<String, Integer> entry : map.entrySet()) {
        String key = entry.getKey();
        Integer value = entry.getValue();
        // use key and value
    }
    System.out.println("Alt #2 took "+(System.currentTimeMillis()-start)+" ms");
}

结果(一些有趣的)

随着 int mapSize = 5000; int strLength = 5;

Alt #1 耗时 26 毫秒

Alt #2 耗时 20 毫秒

随着 int mapSize = 50000; int strLength = 5;

Alt #1 耗时 32 毫秒

Alt #2 耗时 20 毫秒

随着 int mapSize = 50000; int strLength = 50;

Alt #1 耗时 22 毫秒

Alt #2 耗时 21 毫秒

随着 int mapSize = 50000; int strLength = 500;

Alt #1 耗时 28 毫秒

Alt #2 耗时 23 毫秒

随着 int mapSize = 500000; int strLength = 5;

Alt #1 耗时 92 毫秒

Alt #2 耗时 57 毫秒

…等等

原文由 Amol Katdare 发布,翻译遵循 CC BY-SA 4.0 许可协议

第二个片段会稍微快一些,因为它不需要重新查找键。

所有 HashMap 迭代器调用 nextEntry 方法,返回一个 Entry<K,V>

您的第一个片段丢弃了条目中的值(在 KeyIterator 中),然后在字典中再次查找它。

您的第二个片段直接使用键和值(来自 EntryIterator

keySet()entrySet() 都是便宜的电话)

原文由 SLaks 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题