遍历map的四种方法及性能比较
“写代码时,每次都要告诉自己:最后负责维护代码的,会是一个知道你住在哪的变态暴力狂。"——约翰·伍德(John Woods)
昨天在公司用FindBugs插件扫了下组里的代码,发现很多map遍历的性能问题,在这里做个总结和分享,大家有什么不同意见可以随时提。(以下基于HashMap测试,文末还有彩蛋)
· 遍历map的四种方式
方式一:通过遍历map的keyset
// 方法一:遍历keySet clock.start("遍历keySet"); Set<String> keySet = map.keySet(); for (String key : keySet) { String value = map.get(key); } clock.stop();
方式二:使用map的entrySet
// 方法二:使用entrySet clock.start("使用entrySet"); Set<Map.Entry<String, String>> entries = map.entrySet(); for (Map.Entry<String, String> entry : entries) { String value = entry.getValue(); } clock.stop();
方式三:使用迭代器iterator
// 方式三:使用iterator clock.start("使用iterator"); Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry<String, String> next = iterator.next(); String value = next.getValue(); } clock.stop();
方式四:使用map的values方法
// 方式四:使用values clock.start("使用values"); for (String v : map.values()) { String value = v; } clock.stop();
· 耗时比较
Map<String, String> map = new HashMap<>(); for (int i = 0; i < 1000000; i ++) { map.put(String.valueOf(i), "value:" + i); }
构造了一个简单的HashMap,使用四种方法循环跑了5次,结果如下: 第一次:
第二次:
第三次:
第四次:
第五次:
· 总结
1、总的来开,使用iterator迭代器的效率通常是最好的;使用map的keySet遍历value性能最差。 2、结合具体情况:如果只需要遍历出map的所有key,那么keySet无疑是最合适的,因为没有取出value,节省了不必要的空间浪费。
· 小彩蛋
我们都知道,Java标准类库包含了多种Map的基本实现,包括:HashMap、TreeMap、LinkedHashMap、WeakHashMap、ConcurrentHashMap、IdentityHashMap。
由于他们的数据结构不同,行为特征也各不相同,具体表现在效率、键值对保存、呈现次序等多个方面。
就本文的主题来说,TreeMap的结论会更加突出,而WeakHashMap、IdentityHashMap的结论则会有很大不同,感兴趣的话大家可以自己去试试,顺便看一下各种map的实现及源码,会让你对本文结论有更深入的理解。😐