引用
场景:偶尔生产环境的某台机器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.entrySet()`和增强型for循环遍历键和值 这种方法同样利用了`entrySet`视图,但是使用的是增强型for循环而非迭代器。这种方式更加简洁明了,...
- `std::unordered_map`:遍历哈希表通常需要遍历所有桶,因此其时间复杂度也是O(n),但实际运行速度可能比`std::map`快,尤其是当元素数量很大时。 **查找操作**: - `std::map`:查找操作同样为O(log n),因为...
在Java编程语言中,`Map`接口是一种非常重要的数据结构,它存储键值对,并确保每个键都是唯一的。本文将详细介绍Java中Map集合的三种遍历方法及其应用...理解并熟练掌握这些遍历技巧,有助于编写更加高效、优雅的代码。
在处理数据时,我们经常需要遍历`Map`中的元素。本文将详细探讨在Java中遍历`Map`的两种常用方法:通过`keySet()`方法和通过`entrySet()`方法。 ### 一、通过`keySet()`方法遍历`Map` #### 方法概述 `keySet()`...
遍历Map的所有元素是常见的操作,特别是在处理数据或者进行调试时。本文将详细讲解两种主要的遍历Map元素的方法,并分析它们的效率差异。 ### 方法一:通过`entrySet()`遍历 这是推荐的遍历Map元素的方式,因为它...
Map对象提供了一种高效的方式来管理和遍历这些键值对。在JavaScript中,遍历Map对象通常有两种主要的方法:使用`for...of`循环和使用`Map.prototype.forEach()`方法。 首先,让我们来看看在给定的描述中展示的简单...
### Java中遍历Map的四种方式及性能比较 在Java编程中,`Map`是一种非常重要的数据结构,用于存储键值对。...通过了解这些遍历方式的优缺点及适用场景,可以帮助开发者编写出更高效、更易于维护的代码。
在Struts2中,Map遍历是一个常见的功能,它允许开发者动态地展示或操作存储在Map中的数据。这个功能在处理表单提交、传递参数或者在视图层展示数据时尤为有用。 首先,让我们理解Map遍历的基本概念。Map是一种键值...
### Map遍历方法总结 #### 一、引言 在Java编程中,`Map`是一种常用的集合类型,用于存储键值对数据。由于其高效的数据查找特性,在许多场景下都有广泛的应用。对于开发者来说,了解如何有效地遍历`Map`中的元素是...
在Java 8中,Map接口引入了新的方法和特性,使得遍历Map变得更为简洁高效。以下是关于Java 8独有的Map遍历方式的详细说明: 1. **通过`Map.keySet()`遍历** 在Java 8之前,遍历Map的传统方式是通过`Map.keySet()`...
一般来说,第三种方法(通过增强型`for`循环遍历`Map.entrySet()`)是最为简洁和高效的,因为它能够直接访问键值对,避免了额外的`get`操作。而在只需要遍历值的情况下,则可以考虑第四种方法。掌握这些遍历技巧对于...
总结,Java中遍历`Map`主要有四种方式,其中通过`Map.entrySet()`进行遍历通常被认为效率较高,尤其在`Map`容量较大的情况下。而在Java 8之后,我们可以利用Lambda表达式简化遍历操作。获取`Map`的长度直接调用`size...
这种方式比第一种方式更加高效,因为我们可以在遍历过程中同时获取键和值。 第三种方式:通过Iterator遍历获取键和值 在第三种方式中,我们可以使用Iterator对象来遍历Map集合中的键和值。示例代码如下: ```java ...
3. **遍历Map**:使用`<#list>`指令,我们遍历`dataList`中的每一个Map对象,然后再次使用`<#list>`遍历Map中的每一个键值对。 4. **输出结果**:`${key}`和`${value}`分别代表Map中的键和对应的值,它们会被替换为...
### Map遍历方法详解 #### 一、引言 在Java编程中,`Map`是一种常用的集合类型,用于存储键值对数据。由于其高效的数据查找特性,在许多场景下都有广泛的应用。对于开发者来说,掌握如何有效地遍历`Map`中的元素是...
Java Map的遍历方式在实际应用中是一个重要的性能优化考虑因素。常见的遍历方式有三种:keySet、entrySet和values。很多开发者推荐使用entrySet,认为它比keySet更高效,因为entrySet能一次性获取键值对,避免了额外...
这种方式的优点是可以安全地遍历Map的内容,并且可以在遍历过程中修改Map的内容。但是,需要注意的是,使用Iterator遍历需要手动地迭代每个元素,这可能会导致遍历速度相对较慢。 方式四:通过键找值遍历 这种方式...
遍历`map`同样使用迭代器: ```cpp map, int> mapTest; // 添加元素到mapTest map, int>::iterator mapIter; for (mapIter = mapTest.begin(); mapIter != mapTest.end(); ++mapIter) { std::cout << mapIter->...