`

keySet()与entrySet()遍历的性能比较

    博客分类:
  • Java
 
阅读更多
在做项目的时候有邮件发送方面的业务.对邮件的收发的业务不是很清楚,这几天重点在恶搞JavaMail.邮件系统的开发在一般的项目中都会用到,可以看出这一块的知识点用到的频率很高,所以必须来掌握它.这是老大写的一个邮件接口实现类(项目中的真实代码):
package com.tq.platform.service.core.impl;
import java.util.Iterator;  
import java.util.Map;  
  
import javax.activation.DataSource;  
import javax.mail.MessagingException;  
import javax.mail.internet.MimeMessage;  
  
import org.springframework.mail.MailSender;  
import org.springframework.mail.javamail.JavaMailSenderImpl;  
import org.springframework.mail.javamail.MimeMessageHelper;  
  
import com.tq.platform.service.core.MailManager;  
  
/** 
 * 邮件接口实现类 
 *  
 * @author Vincent 
 */  
public class MailManagerImpl extends BaseManagerImpl implements MailManager {  
  
    private MailSender sender;  
  
    public void setSender(MailSender sender) {  
        this.sender = sender;  
    }  
  
    public void sendMessage(String from, String[] to, String subject,  
            String content) {  
        sendMessage(from, to, subject, content, null);  
    }  
  
    public void sendMessage(String from, String[] to, String subject,  
            String content, Map<String, DataSource> attachments) {  
        try {  
    MimeMessage message = ((JavaMailSenderImpl) sender).createMimeMessage();  
    MimeMessageHelper helper = new MimeMessageHelper(message, true,"UTF-8");  
            helper.setFrom(from);  
            helper.setTo(to);  
            helper.setSubject(subject);  
            helper.setText(content, true);  
   if (attachments != null) {
for (Iterator<String> iterator = attachments.keySet().iterator(); iterator.hasNext();) {
                String fileName = iterator.next();
                helper.addAttachment(fileName, attachments.get(fileName));
                }
			}  
          ((JavaMailSenderImpl) sender).send(message);  
        }   
        catch (MessagingException e) {  
            e.printStackTrace();  
        }  
    }  
} 

今天在看这段代码的时候我发现了一个小小的问题那就是老大写的这个遍历:

for (Iterator<String> iterator = attachments.keySet().iterator(); iterator.hasNext();) {
                String fileName = iterator.next();
                helper.addAttachment(fileName, attachments.get(fileName));
               } 

其实这样是没问题的.但我想用entrySet()是不是效率更高一点呢!!!
for (Iterator<Entry<String, DataSource>> iterator = attachments
		.entrySet().iterator(); iterator.hasNext();) {
		Entry<String, DataSource> fileName = iterator.next();
		helper.addAttachment(fileName.toString(), attachments.get(fileName));
				}

当然在数据并发量不大的系统上entrySet()的优势并不明显.
这里我也对entrySet(), keySet()的迭代时间做了一个简单的测试,其 entrySet()的遍历速度并不比keySet()的速度快,但在其应用开发中这些小细节一定要知道.
/**
 * @Title: MapTest.java
 * @Package: cn.tq.java.Test
 * @Description: TODO(用一句话描述该文件做什么)
 * @author: 何枫
 * @date: 2011-9-8 上午11:14:27
 * @version: V1.0
 */
package cn.tq.java.Test;

import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

/**
 * @Title: MapTest.java
 * @Package: cn.tq.java.Test
 * @Description: TODO(用一句话描述该文件做什么)
 * @author: 何枫
 * @date: 2011-9-8 上午11:14:27
 * @version: V1.0
 */
public class MapTest {

	/**
	 * @Title: main
	 * @Description: TODO(这里用一句话描述这个方法的作用)
	 * @param @param args 设定文件
	 * @return void 返回类型
	 * @throws 测试keySet
	 *         ()与entrySet()的迭代时间 keySet():迭代后只能通过get()取key
	 *         entrySet():迭代后可以e.getKey(),e.getValue()取key和value.返回的是Entry接口
	 *         其通过代码的形式验证keySet()的速度比entrySet()慢了很多
	 */
	public static void main(String[] args) {
		Map<String, String> kmap = new HashMap<String, String>();
		Map<String, String> smap = new HashMap<String, String>();
		for (int k = 0; k < 100; k++) {
			kmap.put("" + k, "kmap");
		}
		for (int s = 0; s < 100; s++) {
			smap.put("" + s, "smap");
		}
		long ctimesStart = Calendar.getInstance().getTimeInMillis();
		System.out.println(stimesStart + " " + ctimesStart + "   "
				+ dtimesStart);
		System.out.println("初始化开始时间:" + stimesStart);
		Iterator<String> ktor = kmap.keySet().iterator();
		while (ktor.hasNext()) {
			System.out.print(ktor.next() + "\t");
		}
		/*
		 * Iterator<Entry<String, String>> stor = smap.entrySet().iterator();
		 * while(stor.hasNext()){ Entry<String, String> s = stor.next();
		 * System.out.print(s.getKey()+"\t");
		 * //System.out.print(stor.next().getKey()+"\t"); }
		 */
		long ctimesEnd = Calendar.getInstance().getTimeInMillis();
		System.out.print("\n");
		System.out.print("初始化结束时间:" + ctimesEnd + "\n");
		System.out.print((ctimesEnd - ctimesStart));
	}

}

2
1
分享到:
评论
2 楼 何枫abc 2011-09-09  
scholers 写道
是你的代码里面:
 helper.addAttachment(fileName.toString(), attachments.get(fileName));  


效率低@!因为你遍历之后,在用get方法又产生了此遍历。
JDK里面的源码:get方法:
Java代码
1.  public V get(Object key) {   
2.      if (key == null)   
3.          return getForNullKey();   
4.      int hash = hash(key.hashCode());   
5.      for (Entry<K,V> e = table[indexFor(hash, table.length)];   
6.           e != null;   
7.           e = e.next) {   
8.          Object k;   
9.          if (e.hash == hash && ((k = e.key) == key || key.equals(k)))   
10.             return e.value;   
11.     }   
12.     return null;   
13. }   

解决方法(参考):
Java代码
1.  for (Map.Entry<String, JMenu> entry : menuList.entrySet()) {   
2.      mb.add(entry.getValue()); 



参考:
http://scholers.iteye.com/admin/blogs/1107452

解决方案,这是哪门子解决方案啊!!!还真没看懂,我那个map集合 调用的是add()方法吗???
1 楼 scholers 2011-09-08  
是你的代码里面:
 helper.addAttachment(fileName.toString(), attachments.get(fileName));  


效率低@!因为你遍历之后,在用get方法又产生了此遍历。
JDK里面的源码:get方法:
Java代码
1.  public V get(Object key) {   
2.      if (key == null)   
3.          return getForNullKey();   
4.      int hash = hash(key.hashCode());   
5.      for (Entry<K,V> e = table[indexFor(hash, table.length)];   
6.           e != null;   
7.           e = e.next) {   
8.          Object k;   
9.          if (e.hash == hash && ((k = e.key) == key || key.equals(k)))   
10.             return e.value;   
11.     }   
12.     return null;   
13. }   

解决方法(参考):
Java代码
1.  for (Map.Entry<String, JMenu> entry : menuList.entrySet()) {   
2.      mb.add(entry.getValue()); 



参考:
http://scholers.iteye.com/admin/blogs/1107452

相关推荐

    java-遍历map

    java,利用keySet进行遍历map

    java遍历特例

    // hashmap entrySet() 遍历 for(Map.Entry&lt;Object,Object&gt; m: hash.entrySet()){ System.out.println(m.getKey()+"---"+m.getValue()); } //hashmap keySet() 遍历 for(Object m: hash....

    遍历MAP的几种方法

    遍历MAP的几种方法,利用keyset进行遍历,它的优点在于可以根据你所想要的key值得到你想要的 values,更具灵活性

    Java Map遍历方式的选择

     对于Java中Map的遍历方式,很多文章都推荐使用entrySet,认为其比keySet的效率高很多。理由是:entrySet方法一次拿到所有key和value的集合;而keySet拿到的只是key的集合,针对每个key,都要去Map中额外查找一次...

    java中Map集合的常用遍历方法及HashMap的应用实例

    1、遍历Map.entrySet():它的每一个元素都是Map.Entry对象,这个对象中, 放着的就是Map中的某一对key-value; 2、遍历Map.keySet():它是Map中key值的集合,我们可以通过遍历这个集合来 读取Map中的元素; 3、...

    怎样遍历一个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 ...

    集合嵌套集合并用迭代器输出,有关keySet()和entrySet()的练习

    此文件是用eclipse打包的,如果用eclipse工具可直接导入查看,如果用的是idea工具,可以打开bin下的.class文件之后,拖入到idea运行即可

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

    python库。 资源全名:django-keyset-pagination-plus-0.9.9.tar.gz

    HDCP KSV和keyset对应关系介绍

    HDCP KSV和keyset对应关系介绍HDCP KSV和keyset对应关系介绍HDCP KSV和keyset对应关系介绍HDCP KSV和keyset对应关系介绍HDCP KSV和keyset对应关系介绍HDCP KSV和keyset对应关系介绍HDCP KSV和keyset对应关系介绍HDCP...

    java map集合

    NULL 博文链接:https://hoochiang.iteye.com/blog/1816970

    谈谈Java中遍历Map的几种方法

    java中的map遍历有多种方法,从早的Iterator,到java5支持的foreach,再到java8 Lambda,让我们一起来看下具体的用法以及各自的优缺点。  先初始化一个map public class TestMap {  public static Map&lt;Integer&gt;...

    HashMap 概述 精讲 .md

    - KeySet 内部类 - Values 内部类 - EntrySet 内部类 - HashMap 1.7 的底层结构 - HashMap 1.8 的底层结构 - HashMap 重要属性 - HashMap 构造函数 - 讲一讲 HashMap put 的全过程 - Hash 函数 - 扩容机制...

    java HashMap的keyset实例

    简单地说,在keyset方法返回的set上做修改会改变原来hashmap,这也许不是你想要的,于是形成一个隐藏的bug

    Java使用keySet方法获取Map集合中的元素

    主要为大家详细介绍了Java使用keySet方法获取Map集合中的元素,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

    objection-keyset-pagination:Objection.js 的键集分页(基于光标的分页)插件

    在用户界面方面,键集分页与无限滚动元素配合得很好。 键集分页可提供稳定的结果。 下一批记录总是从上一批的最后一条记录开始,即使查询之间会有插入或删除。 在SQL 中使用Objection.js 自己的.page()或OFFSET等...

    keysetdoes notexist问题解决

    keyset does not exist错误的解决方法

    阿里巴巴编码规范 基础技能认证 考题分析(考题+答案).docx

    B .NULL与任何值的比较结果都为NULL。 C .NULL&lt;&gt;1的返回结果为true。 D .当某一列的值全是NULL时,sum(col)的返回结果为NULL。 多选 7.关于接口使用抛异常还是返回错误码,下列哪些说法符合《阿里巴巴Java开发...

    借助Ehcache缓存框架实现对页面的缓存Demo

    at net.sf.ehcache.store.disk.DiskStore.keySet(DiskStore.java:560) at net.sf.ehcache.store.disk.DiskStorageFactory$DiskExpiryTask.run(DiskStorageFactory.java:838) at java.util.concurrent.Executors$...

    sesvc.exe 阿萨德

    如果当前桶有值( Hash 冲突),那么就要比较当前桶中的 key、key 的 hashcode 与写入的 key 是否相等,相等就赋值给 e,在第 8 步的时候会统一进行赋值及返回。 如果当前桶为红黑树,那就要按照红黑树的方式写入数据...

    Java源码解析HashMap的keySet()方法

    今天小编就为大家分享一篇关于Java源码解析HashMap的keySet()方法,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧

Global site tag (gtag.js) - Google Analytics