Java中怎样遍历HashMap效率最高

Java中遍历HashMap对象中的条目(Entry)时,通常有两种方式:

  1. 通过KeySet遍历
  2. 通过EntrySet遍历

下面的测试分别采用KeySet和EntrySet,通过forEach遍历同一个HashMap对象中的条目。

测试结果表明,方法2通过EntrySet遍历效率优于方法1通过KeySet遍历。

Java代码:

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

import org.junit.BeforeClass;
import org.junit.Test;

public class TestMapTraversal {

    private static int MAXCOUNT = 3000000;
    private static Map<Integer, Integer> map = new HashMap<>(); 
    
    @BeforeClass
    public static void initMap() {
        for (int i = 0; i < MAXCOUNT; i++) {
            map.put(i, i + 1);
        }
    }
    
    @Test
    public void testEntrySet() {
        int sum = 0;
        for (Entry<Integer, Integer> e : map.entrySet()) {
            sum += e.getKey() ^ e.getValue();
        }
        System.out.println(sum);
    }
    
    @Test
    public void testKeySet() {
        int sum = 0;
        for (Integer key : map.keySet()) {
            sum += key ^ map.get(key);
        }
        System.out.println(sum);
    }
    
}

阅读HashMap的源码,对比内部类KeySet和EntrySet中forEach方法的实现。

HashMap.KeySet

public final void forEach(Consumer<? super K> action) {
    Node<K,V>[] tab;
    if (action == null)
        throw new NullPointerException();
    if (size > 0 && (tab = table) != null) {
        int mc = modCount;
        for (int i = 0; i < tab.length; ++i) {
            for (Node<K,V> e = tab[i]; e != null; e = e.next)
                action.accept(e.key);
        }
        if (modCount != mc)
            throw new ConcurrentModificationException();
    }
}

HashMap.EntrySet

public final void forEach(Consumer<? super Map.Entry<K,V>> action) {
    Node<K,V>[] tab;
    if (action == null)
        throw new NullPointerException();
    if (size > 0 && (tab = table) != null) {
        int mc = modCount;
        for (int i = 0; i < tab.length; ++i) {
            for (Node<K,V> e = tab[i]; e != null; e = e.next)
                action.accept(e);
        }
        if (modCount != mc)
            throw new ConcurrentModificationException();
    }
}

实际上两种遍历方式都是对HashMap中的table属性进行遍历,而通过KeySet获取到key之后还需要再次调用get方法,所以效率要差一些。

本文链接:http://bookshadow.com/weblog/2016/10/12/how-to-efficiently-traverse-each-entry-in-java-hashmap/
请尊重作者的劳动成果,转载请注明出处!书影博客保留对文章的所有权利。

如果您喜欢这篇博文,欢迎您捐赠书影博客: ,查看支付宝二维码