首页 > 其他 > 详细

java循环HashMap两种方法的效率比较

时间:2014-02-27 15:12:36      阅读:460      评论:0      收藏:0      [点我收藏+]

一、循环HashMap的两种方式

方式1:

1
2
3
4
5
Iterator<Entry<String, String>> entryKeyIterator = entrySetMap.entrySet().iterator();
       while (entryKeyIterator.hasNext()) {
            Entry<String, String> e = entryKeyIterator.next();
            String value = e.getValue();
}
方式2:
1
2
3
4
5
Iterator<String> keySetIterator = keySetMap.keySet().iterator();
        while (keySetIterator.hasNext()) {
        String key = keySetIterator.next();
        String value = keySetMap.get(key);
}

二、性能比较

到底第一种方式的性能比第二种方式的性能高多少呢,通过一个简单的测试类可以看一下,测试代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class Test {
    public static void main(String[] args) {
        HashMap<String, String> entrySetMap = new HashMap<String, String>();
        HashMap<String, String> keySetMap = new HashMap<String, String>();
        for (int i = 0; i < 500000; i++) {
            entrySetMap.put("" + i, "entrySet");
        }
        for (int i = 0; i < 500000; i++) {
            keySetMap.put("" + i, "keySet");
        }
        long startTimeOne = System.currentTimeMillis();
        Iterator<Entry<String, String>> entryKeyIterator = entrySetMap.entrySet().iterator();
        while (entryKeyIterator.hasNext()) {
            Entry<String, String> e = entryKeyIterator.next();
            //System.out.println(e.getValue());
        }
        StringBuffer result = new StringBuffer("entrySet spent times:");
        result.append((System.currentTimeMillis() - startTimeOne));
        System.out.println(result.toString());
         
        long startTimeTwo = System.currentTimeMillis();
        Iterator<String> keySetIterator = keySetMap.keySet().iterator();
        while (keySetIterator.hasNext()) {
            String key = keySetIterator.next();
            String value = keySetMap.get(key);
            //System.out.println(value);
        }
        result.setLength(0);
        result.append("keyset spent times:");
        result.append((System.currentTimeMillis() - startTimeTwo));
        System.out.println(result.toString());
    }
}

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

三、原因分析

通过查看源代码发现,调用这个方法keySetMap.keySet()会生成KeyIterator迭代器,其next方法只返回其key值

1
2
3
4
5
6
7
8
9
10
private class KeyIterator extends HashIterator<K> {  
    public K next() {
        return nextEntry().getKey();
    }
}  
private class KeyIterator extends HashIterator<K> {
    public K next() {
        return nextEntry().getKey();
    }
}

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

1
2
3
4
5
6
7
8
9
10
private class EntryIterator extends HashIterator<Map.Entry<K,V>> {  
    public Map.Entry<K,V> next() {
        return nextEntry();
    }
}
private class EntryIterator extends HashIterator<Map.Entry<K,V>> {
    public Map.Entry<K,V> next() {
        return nextEntry();
    }
}

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public V get(Object key) {
    Object k = maskNull(key);
    int hash = hash(k);
    int i = indexFor(hash, table.length);
    Entry<K,V> e = table[i];
    while (true) {
        if (e == null)
            return null;
        if (e.hash == hash && eq(k, e.key))
            return e.value;
        e = e.next;
    }
}
public V get(Object key) {
    Object k = maskNull(key);
    int hash = hash(k);
    int i = indexFor(hash, table.length);
    Entry<K,V> e = table[i];
    while (true) {
        if (e == null)
            return null;
        if (e.hash == hash && eq(k, e.key))
            return e.value;
        e = e.next;
    }
}

这个方法就是二者性能差别的主要原因.

java循环HashMap两种方法的效率比较,布布扣,bubuko.com

java循环HashMap两种方法的效率比较

原文:http://www.cnblogs.com/brucetie/p/3569679.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!