HashMap 遍歷的兩種方式及性能比較

HashMap 是Java開(kāi)發(fā)中經(jīng)常使用的數(shù)據(jù)結(jié)構(gòu)。相信HashMap 的基本用法你已經(jīng)很熟悉了。那么我們?cè)撊绾伪闅vHashMap 呢?哪種遍歷方式的性能更好呢?本篇文章來(lái)為你解決這個(gè)疑惑。

一、HashMap 遍歷

如果你了解一些HashMap 底層原理,那么你肯定知道HashMap 是一個(gè)存儲(chǔ)鍵值對(duì)的集合,每個(gè)鍵值對(duì)叫Entry。Entry 組成的數(shù)組構(gòu)成了整個(gè)HashMap 的主干。Entry 的索引是通過(guò)Hash()方法計(jì)算出來(lái)的。因此Entry在數(shù)組內(nèi)部是無(wú)序的(所以我們不能單純的用for語(yǔ)句有序遍歷)。那么我們?cè)撊绾伪闅vHashMap 呢?

1. 使用EntrySet遍歷

HashMap 的內(nèi)部有一個(gè)EntrySet方法可以讓我們方便地獲取HashMap 數(shù)組內(nèi)的所有Entry。假設(shè)我們有一個(gè)這樣的HashMap。

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

我們可以這樣獲取EntrySet。

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

這樣就得到了HashMap 中所有的Entry。獲取Entry 之后遍歷就簡(jiǎn)單多了。我們可以用foreach 語(yǔ)句遍歷

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集合中。再根據(jù)get方法,就可以獲取到每一個(gè)鍵對(duì)應(yīng)的值。 使用KeySet 遍歷的代碼如下:

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

補(bǔ)充一點(diǎn),如果你想獲取Hashmap 中所有的value,你可以用values 方法。該方法返回一個(gè)包含所有value 的collection。

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

二、性能比較

網(wǎng)上對(duì)這兩種遍歷方法進(jìn)行性能比較的文章有很多,我在此就不詳細(xì)比較了。結(jié)論就是,使用EntrySet (也就是第一種方式)進(jìn)行遍歷的性能更好,無(wú)論你是使用foreach還是迭代器,只要你用的是EntrySet 的方式就可以。而KeySet的方式性能就很差,至于KeySet為什么性能很差,我們可以看看遍歷KeySet 時(shí)用到的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;
    }

可以看出來(lái),源碼先獲取了key 對(duì)應(yīng)的hash值 ,然后根據(jù)hash值在HashMap 的Entry 數(shù)組內(nèi)遍歷出hash值與key的hash值相等的Entry,并返回對(duì)應(yīng)的Value。所以get() 方法在獲取Value 的時(shí)候又進(jìn)行了一次循環(huán),這導(dǎo)致了性能的下降。

三、總結(jié)

總結(jié)一下,我們介紹了兩種遍歷HashMap 的方法,一種是用EntrySet,另一種是用KeySet。性能上EntrySet 優(yōu)于KeySet ,這是因?yàn)镵eySet 的get方法在獲取Value 的時(shí)候需要進(jìn)行遍歷。所以推薦遍歷HashMap 的時(shí)候使用EntrySet 的方法。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容