zoukankan      html  css  js  c++  java
  • HashMap 遍历的两种方式及性能比较

    HashMap 是Java开发中经常使用的数据结构。相信HashMap 的基本用法你已经很熟悉了。那么我们该如何遍历HashMap 呢?哪种遍历方式的性能更好呢?本篇文章来为你解决这个疑惑。

    一、HashMap 遍历

    如果你了解一些HashMap 底层原理,那么你肯定知道HashMap 是一个存储键值对的集合,每个键值对叫Entry。Entry 组成的数组构成了整个HashMap 的主干。Entry 的索引是通过Hash()方法计算出来的。因此Entry在数组内部是无序的(所以我们不能单纯的用for语句有序遍历)。那么我们该如何遍历HashMap 呢?

    1. 使用EntrySet遍历

    HashMap 的内部有一个EntrySet方法可以让我们方便地获取HashMap 数组内的所有Entry。假设我们有一个这样的HashMap。

    HashMap<String,Integer> map=new HashMap<String,Integer>();
    

    我们可以这样获取EntrySet。

    Set<Entry<String, Integer>> entrySet=map.entrySet();
    

    这样就得到了HashMap 中所有的Entry。获取Entry 之后遍历就简单多了。我们可以用foreach 语句遍历

    Set<Entry<String, Integer>> entrySet=map.entrySet();
    for (Entry<String, String> entry : entrySet) {
    			System.out.println(entry.getKey()+":"+entry.getValue());
    		}
    

    或者使用迭代器的方式:

    Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();
    		while (iterator.hasNext()) {
    			Map.Entry<String, String> entry = iterator.next();
    			System.out.println(entry.getKey()+":"+entry.getValue());
    		}
    
    2.使用KeySet 遍历

    HashMap 中的KeySet方法可以将把Map中所有的键存入到set集合中。再根据get方法,就可以获取到每一个键对应的值。 使用KeySet 遍历的代码如下:

    for (String key : map.keySet()) {
    			System.out.println(key+":"+map.get(key));
    		}
    

    补充一点,如果你想获取Hashmap 中所有的value,你可以用values 方法。该方法返回一个包含所有value 的collection。

    Collection<String> collection = map.values();
    System.out.println(collection);
    

    二、性能比较

    网上对这两种遍历方法进行性能比较的文章有很多,我在此就不详细比较了。结论就是,使用EntrySet (也就是第一种方式)进行遍历的性能更好,无论你是使用foreach还是迭代器,只要你用的是EntrySet 的方式就可以。而KeySet的方式性能就很差,至于KeySet为什么性能很差,我们可以看看遍历KeySet 时用到的get() 方法的源码(JDK 1.6 ver)。

     public V get(Object key) {
            if (key == null)
                return getForNullKey();
            int hash = hash(key.hashCode());
            for (Entry<K,V> e = table[indexFor(hash, table.length)];
                 e != null;
                 e = e.next) {
                Object k;
                if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
                    return e.value;
            }
            return null;
        }
    

    可以看出来,源码先获取了key 对应的hash值 ,然后根据hash值在HashMap 的Entry 数组内遍历出hash值与key的hash值相等的Entry,并返回对应的Value。所以get() 方法在获取Value 的时候又进行了一次循环,这导致了性能的下降。

    三、总结

    总结一下,我们介绍了两种遍历HashMap 的方法,一种是用EntrySet,另一种是用KeySet。性能上EntrySet 优于KeySet ,这是因为KeySet 的get方法在获取Value 的时候需要进行遍历。所以推荐遍历HashMap 的时候使用EntrySet 的方法。

  • 相关阅读:
    EasyNetQ使用(八)【对延迟消息插件的支持,自动订阅者】
    EasyNetQ使用(七)【发布者确认 ,用Future Publish发布预定中事件 】
    EasyNetQ使用(六)【多态发布和订阅,消息版本控制】
    EasyNetQ使用(五)【基于主题的路由,控制队列名称】
    EasyNetQ使用(四)【Request与Response,Send与Receive】
    可伸缩系统的架构经验
    Stack Exchange 的架构
    Quora使用到的技术
    Digg工程师讲述Digg背后的技术
    由12306.cn谈谈网站性能技术
  • 原文地址:https://www.cnblogs.com/rever/p/8032273.html
Copyright © 2011-2022 走看看