keyword_2 ArrayMap和HashMap及SparseArray

今天來複習一下ArrayMap、HashMap 以及SparseArray間的關聯。

很多時候,我們都很習慣行的使用HashMap,也不用考慮內存問題。當然大部分情況我們都是存儲小數據,但是如果涉及到了數據量很大的時候或者說公司有要求性能這一塊,這個時候,HashMap就會存在內存問題。下面的圖表來自https://www.jianshu.com/p/7b9a1b386265這位朋友。非常感謝。

                       

這個圖就是HashMap的組成結構。可以看出,hashmap是數組加上鍊表的形式組成,也就是哈希表的拉鍊結構(數組+鏈表),默認的數組長度是16,每一個節點都是一個entry。Entry含有key,value,next下一個Entry,以及hash值。這些Entry根據元素keyd的hash值(hash(key))和數組長度求餘,然後根據求餘的值,存在數組對應的下標位置。如hash(3)=3,hah(5)=5;hash(19) = 19 ;分別求餘  hash(3)/16=3;hash(5)/16 = 5;hash(19)/16 = 3;那麼hash(3)和hash(19)就存在數組小標爲3的位置,hash(5)存在數組下標爲5的位置。

            

前面說過,HashMap的存儲是一個長度爲16的數組,也就是隻要new一個hashmap就得分配這個大小的空間給它,即使沒有任何數據。如果當不停的put增加數據的話,如果超過了容量限制時,就會擴容。而且每次都是兩倍擴容。

源碼是這樣的:

if (size++ > threshold) { 
    tab = doubleCapacity(); 
    index = hash & (tab.length - 1); 
} 
doubleCapacity()方法中主要方法在makeTable(newCapacity)中。
private HashMapEntry<K, V>[] makeTable(int newCapacity) { 
    @SuppressWarnings("unchecked") HashMapEntry<K, V>[] newTable 
            = (HashMapEntry<K, V>[]) new HashMapEntry[newCapacity]; 
    table = newTable; 
    threshold = (newCapacity >> 1) + (newCapacity >> 2); // 3/4 capacity 
    return newTable; 
} 
ArrayMap的存儲是通過兩個數組來實現。


ArrayMap的查找是通過二分法查找的,如果數據量小,hashmap和Arraymap沒有什區別,當數據量大的時候,查找速率會比hashmap慢。不過在內存這一方面,ArrayMap要比HashMap節省。ArrayMap每次是通過copy的形式。而不是像HashMap每次new一個。創建二倍空間。

SparseArray也是通過兩個數組來存儲。不過SparseArray只能存儲key爲int類型的。少一個裝箱的操作。其他的和ArrayMap基本上差不多,也是二分法查找。所以如果說存儲key值爲int類型的時候,使用SparseArray比較好。就比如我們viewholder封裝的時候,用的就是SparseArray.

總之。主要幾點不同是:ArrayMap內存空間佔用小(copy的方式創建新空間),但是速率慢(採用二分法查找)。HashMap採用拉鍊結構,查找速率快,只是內存佔用大,每次都要new,擴容是雙倍擴容。SpareArray在key爲int類型的時候,優勢較大。推薦使用。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章