一、循环HashMap的两种方式

方式1:

Iterator<Entry<String, String>> entryKeyIterator = entrySetMap.entrySet().iterator();
while (entryKeyIterator.hasNext()) {
Entry<String, String> e = entryKeyIterator.next();
String value = e.getValue();
}

方式2:

Iterator<String> keySetIterator = keySetMap.keySet().iterator();
while (keySetIterator.hasNext()) {
String key = keySetIterator.next();
String value = keySetMap.get(key);
}

二、性能比较

到底第一种方式的性能比第二种方式的性能高多少呢,通过一个简单的测试类可以看一下,测试代码如下

public class Test {
public static void main(String[] args) {
HashMap<String, String> entrySetMap = new HashMap<String, String>();
HashMap<String, String> keySetMap = new HashMap<String, String>();
for (int i = 0; i < 500000; i++) {
entrySetMap.put("" + i, "entrySet");
}
for (int i = 0; i < 500000; i++) {
keySetMap.put("" + i, "keySet");
}
long startTimeOne = System.currentTimeMillis();
Iterator<Entry<String, String>> entryKeyIterator = entrySetMap.entrySet().iterator();
while (entryKeyIterator.hasNext()) {
Entry<String, String> e = entryKeyIterator.next();
//System.out.println(e.getValue());
}
StringBuffer result = new StringBuffer("entrySet spent times:");
result.append((System.currentTimeMillis() - startTimeOne));
System.out.println(result.toString()); long startTimeTwo = System.currentTimeMillis();
Iterator<String> keySetIterator = keySetMap.keySet().iterator();
while (keySetIterator.hasNext()) {
String key = keySetIterator.next();
String value = keySetMap.get(key);
//System.out.println(value);
}
result.setLength(0);
result.append("keyset spent times:");
result.append((System.currentTimeMillis() - startTimeTwo));
System.out.println(result.toString());
}
}

通过测试发现,第一种方式的性能通常要比第二种方式高一倍

三、原因分析

通过查看源代码发现,调用这个方法keySetMap.keySet()会生成KeyIterator迭代器,其next方法只返回其key值

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

而调用entrySetMap.entrySet()方法会生成EntryIterator 迭代器,其next方法返回一个Entry对象的一个实例,其中包含key和value

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

二者在此时的性能应该是相同的,但方式一再取得key所对应的value时,此时还要访问Map的这个方法,这时,方式一多遍历了一次table

public V get(Object key) {
Object k = maskNull(key);
int hash = hash(k);
int i = indexFor(hash, table.length);
Entry<K,V> e = table[i];
while (true) {
if (e == null)
return null;
if (e.hash == hash && eq(k, e.key))
return e.value;
e = e.next;
}
}
public V get(Object key) {
Object k = maskNull(key);
int hash = hash(k);
int i = indexFor(hash, table.length);
Entry<K,V> e = table[i];
while (true) {
if (e == null)
return null;
if (e.hash == hash && eq(k, e.key))
return e.value;
e = e.next;
}
}

这个方法就是二者性能差别的主要原因.

java循环HashMap两种方法的效率比较的更多相关文章

  1. ubuntu 安装JAVA jdk的两种方法:

    ubuntu 安装jdk 的两种方式: 1:通过ppa(源) 方式安装. 2:通过官网下载安装包安装. 这里推荐第1种,因为可以通过 apt-get upgrade 方式方便获得jdk的升级 使用pp ...

  2. Java对象排序两种方法

    转载:https://blog.csdn.net/wangtaocsdn/article/details/71500500 有时候需要对对象列表或数组进行排序,下面提供两种简单方式: 方法一:将要排序 ...

  3. java异常处理的两种方法

    一种是try-catch-finally,监视代码段,如果有异常就捕获. 另一种是此处不处理,声明在方法后面,抛给上级.(不处理也是一种处理)

  4. [转]Shell脚本之无限循环的两种方法

    方法一: while循环,用的比较多的 #!/bin/bash set j= while true do let "j=j+1" echo "----------j is ...

  5. java连接数据库的两种方法总结

    方法一:使用jdbc-odbc桥连接sql server,作为中间媒介连接数据库 1.配置数据源:打开控制面版->管理工具->数据源(ODBC)->选用户DSN,按下添加按钮-> ...

  6. Shell脚本之无限循环的两种方法

    for #!/bin/bash ;i<;)) do let "j=j+1" echo "-------------j is $j ----------------- ...

  7. Java 创建线程的两种方法

    Java提供了线程类Thread来创建多线程的程序.其实,创建线程与创建普通的类的对象的操作是一样的,而线程就是Thread类或其子类的实例对象.每个Thread对象描述了一个单独的线程.要产生一个线 ...

  8. 遍历Map key-value的两种方法

    以前遍历Map key-value比较习惯的方式是先获取Map中的所有key值,然后根据key,依次从Map中去数据,基本方式如下: Map<String,String> testData ...

  9. 【java基础 13】两种方法判断hashmap中是否形成环形链表

    导读:额,我介绍的这两种方法,有点蠢啊,小打小闹的那种,后来我查了查资料,别人都起了好高大上的名字,不过,本篇博客,我还是用何下下的风格来写.两种方法,一种是丢手绢法,另外一种,是迷路法. 这两种方法 ...

随机推荐

  1. php fpm start.sh

    #! /bin/bash #Source function library. . /etc/init.d/functions #Check that networking is up. . /etc/ ...

  2. JQuery初识

    一.什么是JQuery       JQuery官方网站上是这样解释的:JQuery是一个快速简洁的JavaScript库,它可以简化HTML文档的元素遍历.事件处理.动画及Ajax交互,快速开发We ...

  3. 本地搭建php环境

    AppServ 是 PHP 网页架站工具组合包,所包含的软件有:Apache[.Apache Monitor.PHP.MySQL.phpMyAdmin等,如果您的本地机器没有安装过php.mysql等 ...

  4. laravel安装说明

    1.composer已安装.没安装可以看我上一篇 :http://www.cnblogs.com/seakt/p/4503249.html 2.配置环境变量,找到composer的位置,一般默认都在 ...

  5. C#进程管理程序实现

    运行效果图 部分代码如下: #region 打开应用程序按钮事件处理程序 /// <summary> /// 打开应用程序按钮事件处理程序 /// </summary> /// ...

  6. 一起来看看css中的单位

    一起来看看css中的单位 由于一直以来对于css中的百分比单位究竟是相对于谁的比例,这个问题不是很了解,所以就专门找资料看了一下. <div class="container w500 ...

  7. ubuntu openStack icehouse dashboard theme自定义

    1,ubuntu openStack 语言包locate

  8. svn+ssh

    According to official document, svn+ssh is supposed to be somehow faster than apache+dav_svn, howeve ...

  9. js执行环境相关

    Js执行过程 如果一个文档中存在多个代码段 步骤一:读入第一个代码段(js引擎并非一行一行执行,而是一段一段分析执行) 步骤二:做词法分析和语法分析,有错则报语法错误(比如括号不匹配等),并跳转到步骤 ...

  10. LINQ实现行列转换

    用SQL语句实现行列转换很容易,但也有时候需要在程序中实现,找了好久,发现一篇文章写的挺不错的 http://blog.csdn.net/smartsmile2012/article/details/ ...