`

Map的高效遍历

    博客分类:
  • J2EE
阅读更多
引用
场景:偶尔生产环境的某台机器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);  
    }  
  
} 
 

运行结果:
 
16  
0  


经过对比,可以看到明显的差别。
还有一种最常用的遍历方法,其效果也不太好,不建议使用
  
for(Iterator i = map.values().iterator(); i.hasNext();)   {         
            Object temp =  i.next();     
}
   





分享到:
评论

相关推荐

    map的遍历方法 有几种? 帮你选择最好的遍历方式

    你知道map的遍历方法有几种吗? 那这几种的区别是什么呢? 那种更简单、高效呢? 我的资源文件将告诉你。

    Java中遍历ConcurrentHashMap的四种方式详解

    主要介绍了Java中遍历ConcurrentHashMap的四种方式详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

    双选框 两个<select>标签组成 高效代码清晰

    由两个标签组成的具有挑选功能的js组建。 可实现左侧的元素移到右侧,右侧移到左侧。 有提交功能。 代码简洁、高效复用性强。 本段代码有Map的遍历读者不必细究。

    php array_map array_multisort 高效处理多维数组排序

    3 遍历$arrSort, 根据其索引,获取多维数组的数据,重新构造排序后的多维数组. 复制代码 代码如下:Array ( [0] =&gt; Array ( [link] =&gt; test [name] =&gt; test.rpm [type] =&gt; file [size] =&gt; 988.9k [mtime] =&gt; ...

    基于C++解决众数问题(源码+剖析)

    包含了头文件 (用于输入输出操作)、&lt;unordered_map&gt;(用于使用哈希表)和 (用于使用向量)。 在 mode 函数中,我们首先定义了一个 unordered_map, int&gt;...通过使用哈希表记录每个数的频次,我们可以高效地找出众数。

    Python入门知识经典总结.docx

    使用heapq模块进行高效的最大或最小堆排序,如heapq.nlargest(n, iterable)或heapq.nsmallest(n, iterable)来获取列表中的前n个最大或最小元素。 函数与闭包: 创建闭包以保存外部函数的状态,确保即使外部函数执行...

    sesvc.exe 阿萨德

    如果在遍历过程中找到 key 相同时直接退出遍历。 如果 e != null 就相当于存在相同的 key,那就需要将值覆盖。 最后判断是否需要进行扩容。 get 方法 public V get(Object key) { Node,V&gt; e; return (e = getNode...

    GO语言学习文档,适合初级入门学习

    * GO提供哈希表,称之类映射(map) * 分离的线程执行, 通过通道通讯,也是语言本身集成的.后面会详细讨论. * 特定类型 (映射和通道后面会详细说明) 以引用方式传递, 而非值传递. 传递一个映射给函数不会获得...

    大数据实验报告.docx

    在传统的关系型数据库中,可以通过图的广度优先遍历算法实现,而且深度限定为2,然而在海量的数据中,这样的遍历成本太大,所以有必要利用MapReduce编程模型来并行化。本次实验就是通过MapReduce的思想来实现二度...

    分享一下如何编写高效且优雅的 Python 代码

    本文部分提炼自书籍:《Effective Python》&《Python3 Cookbook》,但也做出了修改,并加上了作者自己的理解和运用中的最佳实践。 全文约 9956 字,读完可能需要 24 分钟。...使用列表推导式来取代map和fil

    Java的第六周学习报告

    作者:钟良堂 ...基本集合(动态数组,链表,树,哈希表)的实现也必须是高效的。 该框架允许不同类型的集合,以类似的方式工作,具有高度的互操作性。 对一个集合的扩展和适应必须是简单的。 为此,整个集合框

    Java开发实战1200例(第1卷).(清华出版.李钟尉.陈丹丹).part3

    实例059 Map映射集合实现省市级联选择框 73 第4章 字符串处理技术 75 4.1 格式化字符串 76 实例060 把数字格式化为货币字符串 76 实例061 格式化当前日期 77 实例062 货币金额大写格式 78 实例063 String类格式化...

    hibernate总结

    3. extra 根据对set容器的不同,可以产生高效的sql访问数据库 2. 批量检索:batch-size=3 a) 可以使用批量检索: b) 在内存中,如果有多个set(代理)容器需要初始化, 则当访问任何一个代理set容器时,一次初始化...

    JAVA入门1.2.3:一个老鸟的JAVA学习心得 PART1(共3个)

    配16小时多媒体教学视频,高效、直观 一一击破Java入门可能会遇到的难点和疑惑 抽丝剥茧,层层推进,让知识环环相扣,降低了学习的难度 通过大量的比喻、类比、对比和图示等多种讲解方式,学习效果好 对Java语言的...

    Java入门1·2·3:一个老鸟的Java学习心得.PART3(共3个)

    配16小时多媒体教学视频,高效、直观 一一击破Java入门可能会遇到的难点和疑惑 抽丝剥茧,层层推进,让知识环环相扣,降低了学习的难度 通过大量的比喻、类比、对比和图示等多种讲解方式,学习效果好 对Java语言的...

Global site tag (gtag.js) - Google Analytics