java循环HashMap两种方法的效率比较
一、循环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两种方法的效率比较的更多相关文章
- ubuntu 安装JAVA jdk的两种方法:
ubuntu 安装jdk 的两种方式: 1:通过ppa(源) 方式安装. 2:通过官网下载安装包安装. 这里推荐第1种,因为可以通过 apt-get upgrade 方式方便获得jdk的升级 使用pp ...
- Java对象排序两种方法
转载:https://blog.csdn.net/wangtaocsdn/article/details/71500500 有时候需要对对象列表或数组进行排序,下面提供两种简单方式: 方法一:将要排序 ...
- java异常处理的两种方法
一种是try-catch-finally,监视代码段,如果有异常就捕获. 另一种是此处不处理,声明在方法后面,抛给上级.(不处理也是一种处理)
- [转]Shell脚本之无限循环的两种方法
方法一: while循环,用的比较多的 #!/bin/bash set j= while true do let "j=j+1" echo "----------j is ...
- java连接数据库的两种方法总结
方法一:使用jdbc-odbc桥连接sql server,作为中间媒介连接数据库 1.配置数据源:打开控制面版->管理工具->数据源(ODBC)->选用户DSN,按下添加按钮-> ...
- Shell脚本之无限循环的两种方法
for #!/bin/bash ;i<;)) do let "j=j+1" echo "-------------j is $j ----------------- ...
- Java 创建线程的两种方法
Java提供了线程类Thread来创建多线程的程序.其实,创建线程与创建普通的类的对象的操作是一样的,而线程就是Thread类或其子类的实例对象.每个Thread对象描述了一个单独的线程.要产生一个线 ...
- 遍历Map key-value的两种方法
以前遍历Map key-value比较习惯的方式是先获取Map中的所有key值,然后根据key,依次从Map中去数据,基本方式如下: Map<String,String> testData ...
- 【java基础 13】两种方法判断hashmap中是否形成环形链表
导读:额,我介绍的这两种方法,有点蠢啊,小打小闹的那种,后来我查了查资料,别人都起了好高大上的名字,不过,本篇博客,我还是用何下下的风格来写.两种方法,一种是丢手绢法,另外一种,是迷路法. 这两种方法 ...
随机推荐
- Linux常用指令(待补充)
1.cd进入目录 2../shuntdown.sh 停止tomcat 3.ps -ef |grep +进程名 查看进程状态 4.kill +进程名 强杀kill -9 +进程 5./start ...
- BZOJ 3439: Kpm的MC密码( trie + DFS序 + 主席树 )
把串倒过来插进trie上, 那么一个串的kpm串就是在以这个串最后一个为根的子树, 子树k大值的经典问题用dfs序+可持久化线段树就可以O(NlogN)解决 --------------------- ...
- Nginx启动报错:10013: An attempt was made to access a socket in a way forbidden
Nginx在win7,win2008下启动报错:bind() to 0.0.0.0:80 failed (10013: An attempt was made to access a socket i ...
- tag标签添加删除并把值存入到一个input的value内
html: <input type="text" id="tagValue" style="display: none;" /> ...
- DX9三角形顶点绕序的判断
今天亲自实践了下,终于搞清楚了. 多边形都有2个侧面,观察坐标系中正面朝向摄像机的为多边形为正面朝向多边形,正面偏离摄像机的为多边形为背面朝向多边形,d3d会把背面朝向多边形剔除,即背面消隐. 使用 ...
- this .运算符 和 [] 运算符
首先看这个 这两个运行结果是不一样的 前两个是3 后面是10 var length = 10; var arr = [function(){console.log(this.length);},2 ...
- SQL Server 数据岸问题
create table t2(x int constraint pk_t2 primary key);go insert into t2(x) values(1),(2),(3),(5),(7),( ...
- Thread-safety with regular expressions in Java
As mentioned in our introduction to the Pattern and Matcher classes, the Java regular expression API ...
- android ListView的上部下拉刷新下部点击加载更多具体实现及拓展
android ListView的上部下拉刷新下部点击加载更多具体实现及拓展 ListView下拉刷新,上拉自动加载更多 下拉刷新以及加载更多
- Eclipse启动后一直Initializing Java Tooling (1%)
问题症状: 工作中eclipse崩溃,再次启动后cpu占用99%,状态栏一直显示Initializing Java Tooling: (1%). 解决方案: 删除\workspace\.metadat ...