遍历map 哪种方式更加高效。
场景:偶尔生产环境的某台机器CPU使用率很高,经过定位发现是有一个大的HashMap(HashMap里面存放了大量数据,比如1W条)做循环引起的。
代码中采用了如下的遍历
?
for(Iterator ite = map.keySet().iterator(); ite.hasNext();){ Object key = ite.next(); Object value = map.get(key);}?
? 通过Map类的get(key)方法获取value时,会进行两次hashCode的计算,消耗CPU资源;而使用entrySet的方式,map对象会直接返回其保存key-value的原始数据结构对象,遍历过程无需进行错误代码中耗费时间的hashCode计算;这在大数据量下,体现的尤为明显。
以下是HashMap.get()方法的源码:
public V get(Object key) { if (key == null) return getForNullKey(); int hash = hash(key.hashCode()); for (Entry<K,V> e = table[indexFor(hash, table.length)]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || key.equals(k))) return e.value; } return null; }?
?
正确用法如下:
?
for(Iterator ite = map.entrySet().iterator(); ite.hasNext();){ Map.Entry entry = (Map.Entry) ite.next(); entry.getKey(); entry.getValue();}?
?
对比测试
?
public class HashMapTest { public static void getFromMap(Map map){ for(Iterator ite = map.keySet().iterator(); ite.hasNext();){ Object key = ite.next(); Object value = map.get(key); } } public static void getFromMapByEntrySet(Map map){ for(Iterator ite = map.entrySet().iterator(); ite.hasNext();){ Map.Entry entry = (Map.Entry) ite.next(); entry.getKey(); entry.getValue(); } } public static void main(String[] args) { Map map = new HashMap(); for(int i=0;i<200000;i++){ map.put("key"+i, "value"+i); } long currentTime = System.currentTimeMillis(); getFromMap(map); long currentTime2 = System.currentTimeMillis(); getFromMapByEntrySet(map); long currentTime3 = System.currentTimeMillis(); System.out.println(currentTime2-currentTime); System.out.println(currentTime3-currentTime2); }}?
运行结果:
?
?
?
160
?
?
经过对比,可以看到明显的差别。
还有一种最常用的遍历方法,其效果也不太好,不建议使用
?
for(Iterator i = map.values().iterator(); i.hasNext();) { Object temp = i.next(); } ?
?
?
1 楼 Matol 2012-06-26 打个标记,ok