`

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

相关推荐

    HashMap遍历

    与`keySet()`不同的是,`entrySet()`允许我们同时访问键和值,而无需额外的`get()`操作。这在性能上通常更优,尤其是在频繁访问键值对的场景下。下面是一个使用`entrySet()`遍历`HashMap`的示例: ```java Map, ...

    map遍历的四种方式及性能比较

    ### Java中遍历Map的四种方式及性能比较 在Java编程中,`Map`是一种非常重要的数据结构,用于存储键值对。对于`Map`的遍历,不同的遍历方式有着不同的性能表现以及适用场景。本文将详细介绍四种常见的遍历`Map`的...

    map遍历的四种方法

    这种方法首先获取`Map`的所有键集合(`keySet`),然后通过迭代器或者增强型for循环(也称为foreach循环)遍历这些键,并使用`get()`方法获取与每个键相对应的值。 **示例代码:** ```java public static void main...

    java集合遍历的几种方式总结及详细比较

    Java中提供了多种Map遍历方式,包括通过获取所有的key、通过Map.entrySet使用iterator遍历、通过Map.entrySet遍历等。 1. 通过获取所有的key遍历 ``` Set&lt;Integer&gt; set = map.keySet(); for (Integer in : map....

    map遍历的三种方法

    Map 遍历是集合操作中的一种重要操作,一般来说,有三种方式来遍历 Map 集合:使用 values() 方法遍历、使用 keySet() 方法遍历和使用 entrySet() 方法遍历。 第一种方法:使用 values() 方法遍历 这个方法是最...

    JAVA遍历Map所有元素.doc

    ### 性能比较 在上述的`HashMapTest`类中,通过对比`keySet()`和`entrySet()`遍历HashMap的时间,我们可以看到`entrySet()`方法通常比`keySet()`方法更快。`keySet()`需要两次遍历:一次是转换为迭代器,另一次是从...

    java遍历大容量map的正确方法.pdf

    3. **通过Map.entrySet遍历key和value(增强for循环)** 这种方式与第二种相似,也是遍历entrySet,但使用了Java 5引入的foreach循环,使得代码更加简洁。 ```java for (Map.Entry, String&gt; entry : map.entrySet...

    Java Map遍历方式的选择

    然而,如果Map实现得足够优化,keySet的性能可能会与entrySet相当,甚至在某些情况下优于entrySet。 遍历key或value时,关键在于是否需要同时访问键和值。如果只需要遍历键或值,values方法和keySet的性能可能会...

    JAVA遍历map的几种实现方法代码

    2. **entrySet遍历** `entrySet()`方法返回一个包含Map所有键值对的Set,通过迭代器或增强for循环遍历。这种方法一次性获取键值对,可以直接访问键和值,例如: ```java for (Entry, Object&gt; entry : map....

    java遍历特例

    这种方法通过`keySet()`获取到所有键组成的集合,然后利用增强for循环遍历每个键,并通过`get()`方法获取对应的值。 #### 四、遍历`Map`的不同方法 接下来,文档详细介绍了四种不同的遍历`Map`的方法: 1. **使用`...

    Java.Map的三种遍历方法.docx

    在Java编程中,`Map`接口是集合框架的重要组成部分,用于存储键值对数据。遍历`Map`是常见的操作,可以用来访问或...而entrySet()则在需要同时处理键和值时更为合适,但需要注意性能问题,特别是在大数据量的`Map`中。

    java哈希遍历_哈希遍历_

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

    另一种遍历Map的方式

    今天,我们来讨论一种遍历Map的方式,即使用Map.Entry和Map.entrySet()。 Map.Entry是什么? ---------------- Map.Entry是一个接口,表示一个映射项,里面有Key和Value。它有两个方法:getKey()和getValue(),...

    java-遍历map

    - 使用流API遍历时,虽然代码更简洁,但性能上可能不如传统的迭代器或增强型for循环,尤其是在处理大量数据时。 - `keySet()`方法返回的是键的集合视图,这意味着对返回的`Set`集合的任何修改都会反映到`Map`上,...

    Java HashMap三种循环遍历方式及其性能对比实例分析

    HashMap提供了三种循环遍历方式,即for each map.entrySet()、显示调用map.entrySet()的集合迭代器、for each map.keySet()。每种遍历方式都有其特点和优缺势,本文将通过实例分析和性能测试来比较这三种遍历方式的...

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

    与`keySet()`相比,`entrySet()`提供了更全面的访问Map内容的方式,因为一次操作就能同时访问键和值。 在集合的嵌套合并中,我们可能需要将多个Map或其他集合类型的对象合并成一个大的集合。例如,如果我们有两个...

    Java Map 遍历比较齐全的解析.docx

    这是最基础的遍历方式,通过获取`Map`的`keySet`,然后用增强型for循环遍历`keySet`,再通过`get()`方法获取对应的`value`。 ```java for (Integer in : map.keySet()) { String str = map.get(in); System.out...

    Java四种遍历Map的方法

    本文将介绍四种遍历Map的方法,分别是通过键值遍历、通过值遍历、通过EntrySet遍历和直接遍历EntrySet。 第一种:通过键值遍历 通过键值遍历是指先获取Map的键值,然后通过键值获取对应的值。这种方法可以通过Map的...

Global site tag (gtag.js) - Google Analytics