HashMap的遍历有两种方式,一种是entrySet的方式,另外一种是keySet的方式。

第一种利用entrySet的方式:

Map map = new HashMap();
Iterator iter = map.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
Object key = entry.getKey();
Object val = entry.getValue();
}

上面的方式可以变化为for循环的形式:

Map<String, String> map = new HashMap<String, String>();
for (Entry<String, String> entry : map.entrySet()) {
entry.getKey();
entry.getValue();
}

第二种利用keySet的方式:

Map map = new HashMap();
Iterator iter = map.keySet().iterator();
while (iter.hasNext()) {
Object key = iter.next();
Object val = map.get(key);
}

上面的方式也可以变化为for循环的形式:

Map<String, String> map = new HashMap<String, String>();
for (String key : map.keySet()) {
map.get(key);
}

这两种方式那种效率高呢?可以从下面的试验可以看出来:

public class Test
{
public static void main(String[] args)
{
HashMap<String, String> map = new HashMap<String, String>();
for (int i = 0; i < 1000000; i++)
{
map.put(i + "", "hello world");
}
long begin1 = System.currentTimeMillis();
Iterator iterator1 = map.entrySet().iterator();
while (iterator1.hasNext())
{
Map.Entry entry = (Map.Entry) iterator1.next();
Object key1 = entry.getKey();
Object val1 = entry.getValue();
}
long end1 = System.currentTimeMillis();
System.out.println("map.entrySet方式变量花费的时间为:" + (end1 - begin1));
long begin2 = System.currentTimeMillis();
Iterator iterator2 = map.keySet().iterator();
while (iterator2.hasNext())
{
Object key2 = iterator2.next();
Object val2 = map.get(key2);
}
long end2 = System.currentTimeMillis();
System.out.println("map.keySet方式变量花费的时间为:" + (end2 - begin2));
}
}

结论:
经过运行多次,我发现两者的运行时间相差不多,而且没有明确显示出那种变量方式更快一些。有的人可能会觉得第一种变量方式会快一些,因为他们觉
得:keySet方式其实是遍历了2次,一次是转为iterator,一次就从HashMap中取出key所对应的value,而entry方式只遍历了
一次,把key和value都放到了entry中,所以entry方式更快一些。
但是我觉得这种分析的方式比较主观,我们更应该从源码的角度去分析。首先看一下迭代器的源码:

keySet的迭代器:

private final class KeyIterator extends HashIterator<K> {
public K next() {
return nextEntry().getKey();
}
}

entrySet的迭代器:

private final class EntryIterator extends HashIterator<Map.Entry<K,V>> {
public Map.Entry<K,V> next() {
return nextEntry();
}
}

从上面我们可以看到只是返回值不同而已,父类相同,所以性能相差不多。下面我们再看一下get方法的源码:

public V get(Object key) {
if (key == null)
return getForNullKey();
Entry<K,V> entry = getEntry(key);
return null == entry ? null : entry.getValue();
}
final Entry<K,V> getEntry(Object key) {
int hash = (key == null) ? 0 : hash(key);
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 != null && key.equals(k))))
return e;
}
return null;
}

从上面的源码发现get的时间复杂度取决于for循环循环次数,即hash算法。所以两种性能差别不大。从上面的分析来看,我们得到最终的结论:
(1)HashMap的循环,如果既需要key也需要value,直接用下面的即可,foreach简洁易懂。

Map<String, String> map = new HashMap<String, String>();
for (Entry<String, String> entry : map.entrySet()) {
entry.getKey();
entry.getValue();
}

(2)如果只是遍历key而无需value的话,可以直接用下面的方式:

Map<String, String> map = new HashMap<String, String>();
for (String key : map.keySet()) {
// key process
}

原文地址:http://swiftlet.net/archives/1259

HashMap两种遍历数据的方式的更多相关文章

  1. HashMap两种遍历方式的深入研究

    转自:http://swiftlet.net/archives/1259 HashMap的遍历有两种方式,如下所示:第一种利用entrySet的方式:   1 2 3 4 5 6 7 Map map ...

  2. Java HashMap两种遍历方式

    第一种: Map map = new HashMap(); Iterator iter = map.entrySet().iterator(); while (iter.hasNext()) { Ma ...

  3. hashmap两种遍历方法

    第一种:使用entryset来进行遍历 Map map=new HashMap(); Iterator iter=map.entrySet().iterator(); while(iter.hasNe ...

  4. HashMap的两种遍历方式

    HashMap的两种遍历方式 HashMap存储的是键值对:key-value . java将HashMap的键值对作为一个整体对象(java.util.Map.Entry)进行处理,这优化了Hash ...

  5. Map的两种遍历方式

    ********************************************************************************* ****************** ...

  6. Request三种获取数据的方式

    今天在做ajax请求后台代码时,发现ajax的方法都对,但就是请求不了后台代码,后来在同事帮助下才发现前台定义了两个相同参数导致请求出错. 下面记录一下request三种获取数据的方式: 1. Req ...

  7. 两种获取connectionString的方式

    两种获取connectionString的方式 1. public static string connectionString = ConfigurationManager.ConnectionSt ...

  8. Java中有两种实现多线程的方式以及两种方式之间的区别

    看到一个面试题.问两种实现多线程的方法.没事去网上找了找答案. 网上流传很广的是一个网上售票系统讲解.转发过来.已经不知道原文到底是出自哪里了. Java中有两种实现多线程的方式.一是直接继承Thre ...

  9. MYSQL 4种插入数据的方式比较

    4种插入数据的方式 第一种:insert into insert into是最常用的插入数据的方式,可以单条插入,也可以多条,还可以指定从其他表中select然后插入. 详细可以参考:insert语法 ...

随机推荐

  1. cocos2d-x 在android环境下开发遇到的一些bug

    今天在弄一个关于android环境下解析xml的东东,遇到了2个比较麻烦问题 1.android的apk下文件是压缩文件,io.open模式无法读取到数据的, 解决思路就是: CCFileUtils: ...

  2. linux配置ant

    第1步:下载ant ,地址:http://ftp.twaren.net/Unix/Web/apache//ant/binaries/apache-ant-1.9.6-bin.tar.gz apache ...

  3. 淘宝(阿里百川)手机客户端开发日记第六篇 Service详解(三)

    主题:Service与Activity交互通信 问题的引出:现在有个需求,如果我们有一个下载任务,下载时间耗时比较长,并且当下载完毕后,需要更新UI的内容,这时,service中的bindServic ...

  4. 向着目标杀jj

     海外资深实力公司招聘:1.PHP工程师,18-25K2.UI设计师,15-25K3.前端工程师,18-25K4.Python工程师,18-25K5.DBA工程师,18-25K6.服务端工程师,18- ...

  5. move 和 CopyMemory的区别

    Move(ABuffer,P, Sizeof(ABuffer));   //指针传递            Move(ABuffer^,P^, Sizeof(TArrayByte));   //复制内 ...

  6. BestCoder Round #60 1001

    Problem Description You are given a sequence of NNN integers. You should choose some numbers(at leas ...

  7. How to Configure Nginx for Optimized Performance

    Features Pricing Add-ons Resources | Log in Sign up   Guides & Tutorials Web Server Guides Nginx ...

  8. 【OpenStack】OpenStack系列15之OpenStack高可用详解

    高可用 概念 级别 陈本 如何实现 分类 Openstack的HA 虚拟机的HA 虚拟机HA 比较 应用级别HA,Heat的HA模板   组件的HA 示意图 Mysql的HA 三种方式之一——主从同步 ...

  9. 夏令时 DST (Daylight Saving Time) java中的夏令时【转】

    1916年,德国首先实行夏令时,英国因为怕德国会从中得到更大的效益,因此紧跟着也采取了夏令时 1986年至1991年,中华人民共和国在全国范围实行了六年夏令时 サマータイム 夏時間(日本现在没有实行夏 ...

  10. shell脚本批量生成配置文件

    如果管理的站点和服务器较多的情况下,每次修改配置文件都相当痛苦.因而想到了用shell脚本来批量生成配置文件和配置数据.下面这个脚本是为了批量生成nagios监控配置文件的一个shell脚本程序.其原 ...