Java HashMap 遍历方式性能探讨

转载自 Java HashMap 遍历方式性能探讨

关于HashMap的实现这里就不展开了,具体可以参考JDK7与JDK8中HashMap的实现

JDK8之前,可以使用keySet或者entrySet来遍历HashMap,JDK8中引入了map.foreach来进行遍历。

原因:

keySet其实是遍历了2次,一次是转为Iterator对象,另一次是从hashMap中取出key所对应的value。而entrySet只是遍历了一次就把key和value都放到了entry中,效率更高。如果是JDK8,使用Map.foreach方法。

1. keySet和entrySet

1.1 基本用法

keySet:

1
2
3
4
5
6
7
8
9
Map map= new HashMap();
Iterator it=map.keySet().iterator();
Object key;
Object value;
while (it.hasNext()){
key=it.next();
value=map.get(key);
System.out.println(key+ ":" +value);
}

entrySet:

1
2
3
4
5
6
7
8
9
10
Map map= new HashMap();
Iterator it=map.entrySet().iterator();
Object key;
Object value;
while (it.hasNext()){
Map.Entry entry = (Map.Entry)it.next();
key=entry.getKey();
value=entry.getValue();
System.out.println(key+ "=" +value);
}

源码上看:

keySet:

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

entrySet:

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

其实这里已经很明显了,当要得到某个value时,keySet还需要从HashMap中get,entrySet相比keySet少了遍历table的过程,这也是两者性能上的主要差别。

2. Map.foreach

在JDK8以后,引入了Map.foreach。

Map.foreach本质仍然是entrySet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
default void forEach(BiConsumer<? super K, ? super V> action) {
         Objects.requireNonNull(action);
         for (Map.Entry<K, V> entry : entrySet()) {
             K k;
             V v;
             try {
                 k = entry.getKey();
                 v = entry.getValue();
             } catch (IllegalStateException ise) {
                 // this usually means the entry is no longer in the map.
                 throw new ConcurrentModificationException(ise);
             }
             action.accept(k, v);
         }
     }

配合lambda表达式一起使用,操作起来更加方便。

2.1 使用Java8的foreach+lambda表达式遍历Map

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Map<String, Integer> items = new HashMap<>();
items.put( "A" , 10 );
items.put( "B" , 20 );
items.put( "C" , 30 );
items.put( "D" , 40 );
items.put( "E" , 50 );
items.put( "F" , 60 );
 
items.forEach((k,v)->System.out.println( "Item : " + k + " Count : " + v));
 
items.forEach((k,v)->{
     System.out.println( "Item : " + k + " Count : " + v);
     if ( "E" .equals(k)){
         System.out.println( "Hello E" );
     }
});

Reference:

  1.  http://lizhuang.iteye.com/blog/2356044
  2.  http://blog.163.com/fw_long/blog/static/51771186201392982041337/
  3.  https://yq.aliyun.com/articles/44712

猜你喜欢

转载自blog.csdn.net/moakun/article/details/80203644