HashMap两种遍历方式的异同(大数据的情况下)

1.两种遍历方式:

第一种:

Iterator keySetIterator = keySetMap.keySet().iterator();    

        while (keySetIterator.hasNext()) {     

            String key = keySetIterator.next();     

            String value = keySetMap.get(key);   
          //  System.out.println("key:="+key+" ,value:="+value);

           // System.out.println(value);     

        } 

第二种:

        Iterator> entryKeyIterator = entrySetMap.entrySet().iterator();     

        while (entryKeyIterator.hasNext()) {     

            Entry e = entryKeyIterator.next();   
          //  System.out.println("key:="+e.getKey()+" ,value:="+e.getValue());

          //  System.out.println(e.getValue());     

        } 

性能比较:




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

/**
 * @author Administrator
 *
 */
public class testHashMap1 {

    public static void Test(){

        HashMap keySetMap = new HashMap();    

        HashMap entrySetMap = new HashMap();  

        /**
         * 
i=9000000
keyset spent times:313
entrySet spent times:169

i=4000000
keyset spent times:191
entrySet spent times:111

i=9999999
keyset spent times:400
entrySet spent times:342

         * */


        for (int i = 0; i < 9999999; i++) {     

            keySetMap.put("" + i, "keySet");     

        }     

        for (int i = 0; i < 9999999; i++) {     

            entrySetMap.put("" + i, "entrySet");     

        }     

        long startTimeOne = System.currentTimeMillis();     

        Iterator keySetIterator = keySetMap.keySet().iterator();    

        while (keySetIterator.hasNext()) {     

            String key = keySetIterator.next();     

            String value = keySetMap.get(key);   
          //  System.out.println("key:="+key+" ,value:="+value);

           // System.out.println(value);     

        }     

        System.out.println("keyset spent times:"     

                + (System.currentTimeMillis() - startTimeOne));    

        long startTimeTwo = System.currentTimeMillis();     

        Iterator> entryKeyIterator = entrySetMap    

                .entrySet().iterator();     

        while (entryKeyIterator.hasNext()) {     

            Entry e = entryKeyIterator.next();   
          //  System.out.println("key:="+e.getKey()+" ,value:="+e.getValue());

          //  System.out.println(e.getValue());     

        }     

        System.out.println("entrySet spent times:"     

               + (System.currentTimeMillis() - startTimeTwo));     

    }


    /**
     * @param args
     */
    public static void main(String[] args) {
        Test();

    }

}

通过测试发现,第二种方式的性能通常要比第一种方式高一倍.

2.原因分析(jdk1.8)

调用keySetMap.keySet()时执行的源代码是返回一个KeyIterator迭代器,其next方法只返回其key值.

    final class KeyIterator extends HashIterator
        implements Iterator<K> {
        public final K next() { return nextNode().key; }
    }

而调用entrySetMap.entrySet()方法会生成EntryIterator 迭代器,其next方法返回一个Entry对象的一个实例,其中包含key和value.

    final class EntryIterator extends HashIterator
        implements Iterator<Map.Entry<K,V>> {
        public final Map.Entry next() { return nextNode(); }
    }

二者在此时的性能应该是相同的,但方式一再取得key所对应的value时,此时还要访问Map的这个方法,这时,方式一多遍历了一次
hashmap。

    /**
     * Returns the value to which the specified key is mapped,
     * or {@code null} if this map contains no mapping for the key.
     *
     * 

More formally, if this map contains a mapping from a key * {@code k} to a value {@code v} such that {@code (key==null ? k==null : * key.equals(k))}, then this method returns {@code v}; otherwise * it returns {@code null}. (There can be at most one such mapping.) * *

A return value of {@code null} does not necessarily * indicate that the map contains no mapping for the key; it's also * possible that the map explicitly maps the key to {@code null}. * The {@link #containsKey containsKey} operation may be used to * distinguish these two cases. * * @see #put(Object, Object) */ public V get(Object key) { Node e; return (e = getNode(hash(key), key)) == null ? null : e.value; }


    /**
     * Implements Map.get and related methods
     *
     * @param hash hash for key
     * @param key the key
     * @return the node, or null if none
     */
    final Node getNode(int hash, Object key) {
        Node[] tab; Node first, e; int n; K k;
        if ((tab = table) != null && (n = tab.length) > 0 &&
            (first = tab[(n - 1) & hash]) != null) {
            if (first.hash == hash && // always check first node
                ((k = first.key) == key || (key != null && key.equals(k))))
                return first;
            if ((e = first.next) != null) {
                if (first instanceof TreeNode)
                    return ((TreeNode)first).getTreeNode(hash, key);
                do {
                    if (e.hash == hash &&
                        ((k = e.key) == key || (key != null && key.equals(k))))
                        return e;
                } while ((e = e.next) != null);
            }
        }
        return null;
    }

这个 String value = keySetMap.get(key); 的get方法就是二者性能差别的主要原因,重新调用了do ..while循环遍历了一遍hashmap.

你可能感兴趣的:(大数据,java,Windows,eclipse,数据结构,java,SE&java,EE&架构,算法&数据结构,机器学习&深度学习)