测试环境:jdk1.7.0_79\Processor 1.7 GHz Intel Core i5

遍历Map的方式有很多,通常场景下我们需要的是遍历Map中的Key和Value。

更新:增加一个方法对方法一优化,采用foreach循环

写了四个方法:

    /**
     * while循环 map.entrySet().iterator()获取map的value
     * @param map
     */
    public static void getMap1(Map<String,String> map){
    Iterator<Map.Entry<String, String>> iter = map.entrySet().iterator();
        while (iter.hasNext()) {
            Map.Entry<String, String> entry = iter.next();
            String key = entry.getKey();
            String value = entry.getValue();
        }
    }
    
    /**
     * while循环 map.keySet().iterator()获取map的value
     * @param map
     */
    public static void getMap2(Map<String,String> map){
    Iterator<String> it = map.keySet().iterator();
        while (it.hasNext()) {
            String key = it.next();
            String value = map.get(key);
        }
    }
    /**
     * foreach循环map.entrySet()获取map的value
     * getMap1的另一种写法,采用foreach循环.foreach循环的底层实现原理就是迭代器Iterator
     * @param map
     */
    public static void getMap3(Map<String,String> map){
        Set<Map.Entry<String, String>> set = map.entrySet();
        for (Map.Entry<String, String> entry : set) {
            String value = entry.getValue();
            }
    }
    /**
     * foreach循环map.keySet()获取map的value
     * @param map
     */
    public static void getMap4(Map<String,String> map){
    Set<String> set = map.keySet();
    for (String entry : set) {
    String value = map.get(entry);
    }
    }

注:我以前常用的就是方法2,原则就是能用就行。所以第一印象不一定对哦。

默认map中已经存储了数据,map数据量不确定,用户访问量不确定

我采用for循环多次调用getMap方法来模拟用户访问,如下:

 
      HashMap<String, String> map = new HashMap<String, String>();
        int mapNum=1000;//设置map数据量
        int forNum = 1000;//设置for循环调用次数,模拟用户访问次数
        //模拟map已经存储了数据
        for (int i = 0; i < mapNum; i++) {
            map.put("key" + i, "value" + i);
        }
        //用for循环调用getMap来模拟多次访问
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < forNum; i++) {
            getMap1(map);
        }
        System.out.println("getMap1:"+(System.currentTimeMillis() - startTime) + "ms");
 
        startTime = System.currentTimeMillis();
        for (int i = 0; i < forNum; i++) {
            getMap2(map);
        }
        System.out.println("getMap2:"+(System.currentTimeMillis() - startTime) + "ms");
        
        startTime = System.currentTimeMillis();
        for (int i = 0; i < forNum; i++) {
            getMap3(map);
        }
        System.out.println("getMap3:"+(System.currentTimeMillis() - startTime) + "ms");
        startTime = System.currentTimeMillis();
        for (int i = 0; i < forNum; i++) {
        getMap4(map);
        }
        System.out.println("getMap4:"+(System.currentTimeMillis() - startTime) + "ms");
 

(以下测试数据是前三个方法的数据,方法四也类似的结果)

map数据量为10,用户访问10次(for循环调用getMap 10次)

看不出来效果

map数据量为10,用户访问100次(for循环调用getMap 100次)

看不出来效果

map数据量为10,用户访问1000次(for循环调用getMap 1000次)


getMap1:15ms

getMap2:22ms

getMap3:4ms

map数据量为10,用户访问10000次(for循环调用getMap 10000次)

getMap1:27ms

getMap2:31ms

getMap3:15ms

map数据量为10,用户访问100000次(for循环调用getMap 10万次)


getMap1:52ms

getMap2:53ms

getMap3:32ms

map数据量为10,用户访问1000000次(for循环调用getMap 百万次)


getMap1:169ms

getMap2:280ms

getMap3:128ms

百万级别的时候差距拉大了,但有时候1和3差距不大

map数据量为100,for循环调用getMap 100次


getMap1:8ms

getMap2:18ms

getMap3:4ms

一倍差距啊

map数据量为100,for循环调用getMap 1000次


getMap1:23ms

getMap2:28ms

getMap3:14ms

map数据量为100,for循环调用getMap 1万次

getMap1:38ms

getMap2:57ms

getMap3:28ms

map数据量为100,for循环调用getMap 10万次


getMap1:126ms

getMap2:221ms

getMap3:75ms

map数据量为100,for循环调用getMap 百万次


getMap1:641ms

getMap2:1823ms

getMap3:574ms

1和2三倍啊!,不过这个时候1和3差距不大了

后面仅仅是摘选几条:

map数据量为1000,for循环调用getMap 1000次

getMap1:44ms

getMap2:43ms

getMap3:26ms

map数据量为1000,for循环调用getMap 是万次

getMap1:1259ms

getMap2:2420ms

getMap3:887ms

map数据量为1000,for循环调用getMap 百万次


getMap1:11210ms

getMap2:21083ms

getMap3:6941ms

map数据量为10000,for循环调用getMap 10000次

getMap1:2807ms

getMap2:4770ms

getMap3:2511ms

map数据量为10000,for循环调用getMap 百万次


getMap1:167107ms

getMap2:230967ms

getMap3:123263ms

基本上方法一的效率和四差不多,比方法二高一倍,方法三比方法一效率高一些,建议采用方法三。当然实际情况可能很复杂,硬件设备、并发情况,更多的时候仅仅是map数据量大但是访问量小,甚至可能我们采用服务器启动即加载的方式避免了用户访问时遍历。

而且要注意,不同情况下的写法不同,测试结果可能是不一样的。需要注重的是,一旦涉及到遍历的情况,就要考虑数据量和访问量,来选择最佳的遍历方式。

顺便提一句:有些人可能习惯这样写代码

for(int i = 0;i < list.length();i++){}以及foreach语句,我印象中for循环中每次都要计算一次list.length,这也是不必要的开销。foreach在顺序访问中效率高,所以如果是遍历arrayList的时候不要用foreach

更新:如果只是想要遍历一下key呢?方法三不一定比方法二好,方法一肯定比方法二差。例如

map数据量为10000,for循环调用getMap 10000次

getMap1:2767ms

getMap2:1068ms

getMap3:2208ms

根据实际情况选择吧。

欢迎各位补充。



遍历hashMap对效率的影响的更多相关文章

  1. java遍历Hashmap/Hashtable的几种方法

    一>java遍历Hashtabe: import java.util.Hashtable; import java.util.Set; public class HashTableTest { ...

  2. java遍历hashMap、hashSet、Hashtable

    一.遍历HashMap Map<Integer, String> map = new HashMap<Integer, String>(); 方法一:效率高 for(Entry ...

  3. java 中遍历hashmap 和hashset 的方法

    一.java中遍历hashmap:    for (Map.Entry<String, Integer> entry : tempMap.entrySet()) {     String ...

  4. 使用多种方式实现遍历HashMap

    今天讲解的主要是使用多种方式来实现遍历HashMap取出Key和value,首先在java中如果想让一个集合能够用for增强来实现迭代,那么此接口或类必须实现Iterable接口,那么Iterable ...

  5. [Java] 遍历HashMap和HashMap转换成List的两种方式

    遍历HashMap和HashMap转换成List   /** * convert the map to the list(1) */ public static void main(String[] ...

  6. 专题三、ArrayList遍历方式以及效率比较

    一.遍历方式 ArrayList支持三种遍历方式. 1.第一种,随机访问,它是通过索引值去遍历 由于ArrayList实现了RandomAccess接口,它支持通过索引值去随机访问元素. 代码如下: ...

  7. Java遍历HashMap并修改(remove)(转载)

    遍历HashMap的方法有多种,比如通过获取map的keySet, entrySet, iterator之后,都可以实现遍历,然而如果在遍历过程中对map进行读取之外的操作则需要注意使用的遍历方式和操 ...

  8. 四种遍历hashMap的方法及比较

    学习怎样遍历Java hashMap及不同方法的性能. // hashMap的遍历 public void testHashMap() { Map<String, String> map ...

  9. OC各种遍历方法的效率比较

    看了一篇博客,挺有意思,OC各种遍历方法的效率,打算自己也测试一番.看看,究竟哪一个的效率更好一些! 准备工作:懒加载一个数组,创建一千万个对象添加到数组. #pragma mark - Lazy M ...

随机推荐

  1. EF LINQ根据某个字段去除重复行

    1.ydc.GameScore.OrderByDescending(o => o.Score).GroupBy(ic => ic.UserPhone).Select(g => g.F ...

  2. Listener

    通过Listner获得当前的用户个数 package listener; import javax.servlet.ServletContext; import javax.servlet.Servl ...

  3. StackExchange.Redis 官方文档(一) Basics

    基本使用方法: StackExchange.Redis的核心是 StackExchange.Redis 命名空间的 ConnectionMultiplexer 类;它隐藏了多服务器的实现细节.Conn ...

  4. HTML5离线应用与客户端存储

    序言 本篇文章会详细介绍使用HTML5开发离线应用的步骤,以及本地存储与cookie的一些异同,最后利用上面所学例子来实现一个购物车场景. 使用HTML5离线存储的基本过程如下: 离线检测:首先要对设 ...

  5. Java虚拟机——进度1

    Java 虚拟机       一.Java虚拟机的基本结构 ①类加载子系统:从文件系统或者网络中加载Class信息,存放在方法区中. ②方法区中存放放进来的Class信息,也包括一些运行时常量池信息包 ...

  6. sql数据库恢复 文件丢失误删除 误格式化置疑报错修复 数据库置疑修复总结/SQL SERVER 2000/2005/2008/2008R2

    数据库置疑的原因会有多种多样,不同的问题采用的步骤也会有所不同,以下的步骤不能适用所有的情况,但包括了一些基本的步骤. 数据库置疑是指数据库内部处于不一致的状态,很有可能会有数据丢失.我们推荐您从做数 ...

  7. iOS 日期时间控件

    UIDatePicker *picker = [[UIDatePicker alloc]initWithFrame:CGRectMake(0, 0,[UIParam widthScreen] ,50 ...

  8. webstorm常用快捷键及插件

    子曰:工欲善其事,必先利其器.那么问题来了,前端开发用什么比较好? 我反正用的是webstorm,之前也花了一些时间看看别人的使用方式.下面分类介绍一下. 常用快捷键: double shift : ...

  9. Brackets - 强大免费的开源跨平台Web前端开发工具IDE (HTML/CSS/Javascript代码编辑器)

    Brackets 是一个免费.开源且跨平台的 HTML/CSS/JavaScript 前端 WEB 集成开发环境 (IDE工具).该项目由 Adobe 创建和维护,根据MIT许可证发布,支持 Wind ...

  10. C++第五天学习

    回顾: 1.友元 friend 2.运算符重载 类型 operator运算符(参数表) 抽象.封装 类是面向对象程序设计中最基本的概念 类的背后隐藏的思想是数据抽象和封装 是进行封装和数据隐藏的工具, ...