场景:偶尔生产环境的某台机器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的遍历方法有几种吗? 那这几种的区别是什么呢? 那种更简单、高效呢? 我的资源文件将告诉你。
主要介绍了Java中遍历ConcurrentHashMap的四种方式详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
3 遍历$arrSort, 根据其索引,获取多维数组的数据,重新构造排序后的多维数组. 复制代码 代码如下:Array ( [0] => Array ( [link] => test [name] => test.rpm [type] => file [size] => 988.9k [mtime] => ...
由两个标签组成的具有挑选功能的js组建。 可实现左侧的元素移到右侧,右侧移到左侧。 有提交功能。 代码简洁、高效复用性强。 本段代码有Map的遍历读者不必细究。
包含了头文件 (用于输入输出操作)、<unordered_map>(用于使用哈希表)和 (用于使用向量)。 在 mode 函数中,我们首先定义了一个 unordered_map, int> 类型的哈希表 freqMap,用于记录每个数出现的频次。 然后,...
不然就按照链表的方式遍历匹配返回值。 从这两个核心方法(get/put)可以看出 1.8 中对大链表做了优化,修改为红黑树之后查询效率直接提高到了 O(logn)。 但是 HashMap 原有的问题也都存在,比如在并发场景下使用时...
在生活中,二度好友推荐的运用非常广泛,一般在主流的社交平台上关于好友推荐上就有这方面的应用,当然,在当下海量的数据中,利用MapReduce编程模型来实现不失为一种较好的方式,具体的过程如下图。 这里需要同学...
使用heapq模块进行高效的最大或最小堆排序,如heapq.nlargest(n, iterable)或heapq.nsmallest(n, iterable)来获取列表中的前n个最大或最小元素。 函数与闭包: 创建闭包以保存外部函数的状态,确保即使外部函数执行...
* 特定类型 (映射和通道后面会详细说明) 以引用方式传递, 而非值传递. 传递一个映射给函数不会获得函数的一个拷贝, 所以如果函数改变了其值,调用者能看得到. 在C++中可以理解成引用. *GO没有头文件.取而代之地...
作者:钟良堂 ...基本集合(动态数组,链表,树,哈希表)的实现也必须是高效的。 该框架允许不同类型的集合,以类似的方式工作,具有高度的互操作性。 对一个集合的扩展和适应必须是简单的。 为此,整个集合框
本文部分提炼自书籍:《Effective Python》&《Python3 Cookbook》,但也做出了修改,并加上了作者自己的理解和运用中的最佳实践。 全文约 9956 字,读完可能需要 24 分钟。...使用列表推导式来取代map和fil
3. QBC ( query by criteria ) 更加面向对象 4. QBE ( query by Example ) 5. SQL Hibernate的检索策略: 1. 延迟检索(加载)映射文件中改变lazy a) Lazy的取值: i. Many-to-one 1. false 2. proxy 3. ...
实例150 实例化Class类的5种方式 196 实例151 获得Class对象表示实体的名称 197 实例152 查看类的声明 198 实例153 查看类的成员 199 实例154 按继承层次对类排序 201 实例155 查看内部类信息 202 7.2 反射的进阶 ...
通过大量的比喻、类比、对比和图示等多种讲解方式,学习效果好 对Java语言的每个语法都提供了一个或多个例程讲解 大量使用流程图表示程序的执行过程,使用结构图表示程序的内部状态 每章最后都给出了典型的练习题,...
通过大量的比喻、类比、对比和图示等多种讲解方式,学习效果好 对Java语言的每个语法都提供了一个或多个例程讲解 大量使用流程图表示程序的执行过程,使用结构图表示程序的内部状态 每章最后都给出了典型的练习题,...