`

为KeySet遍历HashMap辟谣---效率问题

阅读更多
    听某位高级软件开发工程师说遍历HashMap的三种方式,用KeySet遍历的方式会非常慢,效率特别低,所以推荐使用EntrySet的方式遍历HashMap,这两种都是可以获取到HashMap的key-value对,另外一种遍历HashMap的方式是调用HashMap的values方法,但是无法得到key的值。当听到说keyset特别慢,效率低下的时候,我就在想,如果这样真的那么慢的话,那么jdk是不是早就把这样的方式给废弃了啊,或者加上@Deprecated了。所以我想着证明一下。看以下代码
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public class JudgeHashMap {
	public static void main(String[] args) {
		Map<Integer, Integer> hashMap = new HashMap<Integer, Integer>();
		for (int i = 0; i < 1000000; i++) {
			hashMap.put(i, i);
		}
		long start = System.nanoTime();
		Set<Integer> set = hashMap.keySet();
		Iterator<Integer> iterator = set.iterator();
		while (iterator.hasNext()) {
			iterator.next();
		}
		long mid = System.nanoTime();
		System.out.println("keySet用的时间是" + (mid - start) / 1e10 + "秒");
		long mid2 = System.nanoTime();
		Set<Entry<Integer, Integer>> sEntries = hashMap.entrySet();
		Iterator<Entry<Integer, Integer>> iterator2 = sEntries.iterator();
		while (iterator2.hasNext()) {
			iterator2.next();
		}
		long end = System.nanoTime();
		System.out.println("entrySet用的时间是" + (end - mid2) / 1e10 + "秒");
		long end2 = System.nanoTime();
		Collection<Integer> collection = hashMap.values();
		Iterator<Integer> iterator3 = collection.iterator();
		while (iterator3.hasNext()) {
			iterator3.next();
		}
		long end3 = System.nanoTime();
		System.out.println("values用的时间是" + (end3 - end2) / 1e10 + "秒");
	}
}

   得到的结果是
keySet用的时间是0.0022835033秒
entrySet用的时间是0.0024659158秒
values用的时间是0.0022196947秒
   keyset遍历容量为100万的hashmap用时就比entryset多用了0.0004秒。当hashmap的容量比较小的情况下,两者的差距其实可以忽略不计了。
那到底是因为什么引发了这个时间上的差距呢,原因是keyset是通过entryset得到的,然后通过迭代keyset得到键值对,达到遍历的效果,所以会慢一点,但是绝对不是效率低下。所以当HashMap容量比较小的情况下,完全可以使用keyset的方式。
2
6
分享到:
评论
7 楼 sunway00 2013-08-07  

Map<Integer, String> hashMap = new HashMap<Integer, String>();
		List<String> values1 = new ArrayList<String>(1000000);
		List<String> values2 = new ArrayList<String>(1000000);
		
		
		for (int i = 0; i < 1000000; i++) {  
            hashMap.put(i, "aaaaaaaa");  
        }
		
		long start = System.nanoTime(); 
		
		for (Entry<Integer, String> entry : hashMap.entrySet()) {
			values1.add(entry.getValue());
		}
		
		long end = System.nanoTime();
		
		System.out.println("entrySet用的时间是" + (end - start) / 1e10 + "秒"); 
		
		Set<Integer> keySet = hashMap.keySet();
		long start2 = System.nanoTime();
		for (Integer integer : keySet) {
			values2.add(hashMap.get(integer));
		}
		long end2 = System.nanoTime();
		
		System.out.println("keySet用的时间是" + (end2 - start2) / 1e10 + "秒"); 


运行结果:
entrySet用的时间是0.0034094524秒
keySet用的时间是0.004261786秒

使用entrySet的主要原因是避免在再次执行 map.get(key),而根据测试,时间能相差1ms。
6 楼 Shen.Yiyang 2013-08-07  
ddlgyq 写道
lyplyz 写道
如果你在循环中只用key,则用keySet没问题
但如果你既要用key也要用value,则使用entrySet的效率确实比keySet
因为此时,如果你用keySet,你要多一次value = map.get(key),这个才是最大的消耗,你试试在while循环中把value取出来就知道了

取出value的时间对比,对于百万容量的hashMap的话 时间没差多少吧
keySet用的时间是0.0050171926秒
entrySet用的时间是0.0032048473秒
values用的时间是0.0021337984秒

4楼的意思是说,既然你要测试“获取到HashMap的key-value对”,那么用keyset的时候,就必须在循环里面一次次调用map.get(key),这样就慢了。你现在的测试是只得到了keyset,只是比entryset多做了一次 set的循环,没有获取key-value对。
5 楼 ddlgyq 2013-08-06  
lyplyz 写道
如果你在循环中只用key,则用keySet没问题
但如果你既要用key也要用value,则使用entrySet的效率确实比keySet
因为此时,如果你用keySet,你要多一次value = map.get(key),这个才是最大的消耗,你试试在while循环中把value取出来就知道了

取出value的时间对比,对于百万容量的hashMap的话 时间没差多少吧
keySet用的时间是0.0050171926秒
entrySet用的时间是0.0032048473秒
values用的时间是0.0021337984秒
4 楼 lyplyz 2013-08-06  
如果你在循环中只用key,则用keySet没问题
但如果你既要用key也要用value,则使用entrySet的效率确实比keySet
因为此时,如果你用keySet,你要多一次value = map.get(key),这个才是最大的消耗,你试试在while循环中把value取出来就知道了
3 楼 ddlgyq 2013-08-06  
alvin198761 写道
for(Entry<K,V> entry : hashMap.entrySet()){
//这样就行了,不用那么些,
}

2 楼 alvin198761 2013-08-06  
for(Entry<K,V> entry : hashMap.entrySet()){
//这样就行了,不用那么些,
}
1 楼 bitray 2013-08-06  
你写的很对,虽然老生常谈,但是说明一些高级工程师不求甚解,仅仅是照本宣科

相关推荐

    Java 实例 - HashMap遍历源代码-详细教程.zip

    - 使用`keySet()`遍历并删除元素是安全的,但效率较低,因为这涉及到两次查找:一次找到键,一次找到对应的值。 - 更推荐使用`entrySet()`遍历,可以直接访问键和值,并在遍历过程中删除元素,只需一次查找。 6. ...

    Java 实例 - 集合遍历源代码-详细教程.zip

    最后,HashMap是键值对存储的集合,遍历HashMap需要注意,因为直接遍历可能会出现并发修改异常。一般有两种方式:一是通过keySet()获取键的集合并遍历,二是通过entrySet()获取键值对的集合进行遍历: ```java ...

    [] - 2023-11-11 为什么阿里不推荐使用 keySet() 遍历HashMap?.pdf

    互联网资讯,技术简介,IT、AI技术,人工智能互联网资讯,技术简介,IT、AI技术,人工智能互联网资讯,技术简介,IT、AI技术,人工智能互联网资讯,技术简介,IT、AI技术,人工智能互联网资讯,技术简介,IT、AI技术...

    Java5种遍历HashMap数据的写法

    除了使用EntrySet的迭代器,我们还可以使用KeySet的迭代器来遍历HashMap中的数据。其实现代码如下: ```java Iterator&lt;Integer&gt; iterator = coursesMap.keySet().iterator(); while (iterator.hasNext()) { Integer...

    java遍历HashMap简单的方法

    HashMap遍历的常用方法主要有三种:迭代器(Iterator)遍历、键集(KeySet)遍历以及 Entry 集(entrySet)遍历。下面将逐一介绍这些方法。 1. 迭代器遍历: HashMap提供了迭代器接口(Iterator),可以通过调用`...

    Python库 | django-keyset-pagination-plus-0.9.9.tar.gz

    标题中的“django-keyset-pagination-plus-0.9.9.tar.gz”揭示了这是一个与Python相关的库,特别是针对Django框架的。Django是Python的一种流行Web开发框架,它提供了丰富的功能,包括数据库交互、模板系统、表单...

    基于HashMap遍历和使用方法(详解)

    HashMap遍历和使用方法详解 HashMap是Java中一种常用的数据结构,用于存储键值对的集合。它实现了Map接口,是基于哈希表结构的,可以快速地存储和检索数据。本文将详细介绍HashMap的遍历和使用方法,并比较HashMap...

    使用多种方式实现遍历HashMap的方法

    遍历HashMap是常见的操作,本文将介绍六种不同的方法来实现这一功能。 1. **方式一:使用KeySet方法** KeySet方法返回HashMap中所有键的Set视图。由于Set接口实现了Iterable接口,我们可以使用for-each循环来遍历...

    HashMap遍历

    本文将深入探讨`HashMap`的遍历方法,包括`keySet()`和`entrySet()`两种主要方式,并通过代码示例对比它们的性能差异。 #### 方法一:使用`keySet()`遍历 `keySet()`方法返回`HashMap`中的所有键的集合视图。通过...

    怎样遍历一个HashMap?

    可以通过2种方法遍历HashMap &lt;br&gt;Map map = new HashMap(); &lt;br&gt;for (Iterator iter = map.entrySet().iterator(); iter.hasNext();) { &lt;br&gt; Map.Entry entry = (Map.Entry) iter.next(); &lt;br&gt; Object ...

    HashMap和List遍历方法及如何遍历删除元素总结

    要解决HashMap遍历删除元素的问题,可以使用Iterator来遍历HashMap,并使用Iterator的remove方法来删除元素。这样可以避免ConcurrentModificationException异常。 小结 在遍历和删除HashMap和List的元素时,需要...

    java哈希遍历_哈希遍历_

    使用`Map.keySet()`方法获取HashMap中所有键的`Set`集合,然后通过迭代器遍历这个集合,获取每个键,再通过`map.get(key)`获取对应的值。 ```java for (String key : map.keySet()) { int value = map.get(key)...

    Java HashMap的三种遍历方法及优缺点含示例

    keySet()方法提供了一个包含所有键的Set集合,通过遍历这个Set集合,我们可以获取到HashMap中的每一个键,然后再通过键去get()对应的值。这种方式比较适合只需要使用键的场景。 **优点**:如果只需要键,这种方法...

    java-遍历map

    在Java编程语言中,`Map`接口是一...总之,遍历`Map`是Java编程中常见的需求之一,掌握正确的遍历方法不仅可以提高代码的效率,还可以避免潜在的错误。希望本文的内容能帮助你更好地理解和使用Java中的`Map`遍历技巧。

    浅谈Java中HashMap类的使用.pdf

    HashMap 是 Java 语言中最常用的集合类之一,它实现了 Map 接口,提供了 put、get、keySet 等常用方法来存储和检索数据。本文将详细介绍 HashMap 类的使用,包括其常用方法、特点和应用场景。 一、HashMap 的基本...

    java提高篇(二三)-----HashMap.pdf

    HashMap提供了迭代器(Iterator)和键集(keySet)、值集(values)以及键值对集(entrySet)来进行遍历。 总结来说,HashMap是Java中一种高效的键值对存储结构,其性能依赖于良好的哈希函数、合适的初始容量和...

    如何得到hashmap的索引

    根据提供的内容,我们可以了解到遍历`HashMap`主要有两种方式:使用`keySet()`方法和使用`entrySet()`方法。 1. **使用keySet()方法** ```java Map map = new HashMap(); Iterator iter = map.keySet()....

    另一种遍历Map的方式

    这里,m是一个HashMap,t是一个TextArea,我们使用for循环遍历整个Map,每次迭代都可以获取当前映射项的Key和Value。 ### 方法二:使用Iterator 使用Iterator也可以遍历整个Map,代码如下: ``` Iterator it = ...

    hashmap使用实例

    6. **遍历HashMap**:有两种方式遍历HashMap,一是通过`entrySet()`获取键值对的迭代器,二是通过`keySet()`获取键的迭代器再获取对应的值。 ```java for (Map.Entry, String&gt; entry : map.entrySet()) { System....

    List,Set和Map遍历读取[归类].pdf

    在Java编程语言中,集合框架是处理对象组的重要工具,主要包括List、Set和Map三大类。这些接口由java.util包提供,为数据存储和操作提供了丰富的功能。...了解并熟练掌握这些遍历方法,能够提高代码的可读性和效率。

Global site tag (gtag.js) - Google Analytics