SparseArray分析

weixin_33871366發表於2018-07-31

在寫SparseArray某些情況下比HashMap效能更好,按照官方問答的解釋,主要是因為SparseArray不需要對key和value進行auto-boxing(將原始型別封裝為物件型別,比如把int型別封裝成Integer型別),結構比HashMap簡單(SparseArray內部主要使用兩個一維陣列來儲存資料,一個用來存key,一個用來存value)不需要額外的額外的資料結構

key為int的時候才能使用,注意是int而不是Integer,這也是sparseArray效率提升的一個點,去掉了裝箱的操作

插入

100000條資料的儲存使用DDMS檢視,hashMap的儲存空間14M左右,而SparseArray自由8M多幾乎是少了40%接近
插入時候,SparseArray 正序插入效率比起倒序插入快了幾乎是10倍, hashMap差不多。
我們是按照1,3,2的順序排列的,但是在SparseArray內部還是按照正序排列的,這時因為SparseArray在檢索資料的時候使用的是二分查詢,所以每次插入新資料的時候SparseArray都需要重新排序,所以程式碼4中,逆序是最差情況。

SparseArray原理

單純從字面上來理解,SparseArray指的是稀疏陣列(Sparse array),所謂稀疏陣列就是陣列中大部分的內容值都未被使用(或都為零),在陣列中僅有少部分的空間使用。因此造成記憶體空間的浪費,為了節省記憶體空間,並且不影響陣列中原有的內容值,我們可以採用一種壓縮的方式來表示稀疏陣列的內容。
假設有一個97的陣列,其內容如下

5459476-7dc9f2f5bd6da41e.png
image.png

在此陣列中,共有63個空間,但卻只使用了5個元素,造成58個元素空間的浪費。以下我們就使用
5459476-4cd72b2d004f1efe.png
image.png

其中在稀疏陣列中第一部分所記錄的是原陣列的列數和行數以及元素使用的個數、第二部分所記錄的是原陣列中元素的位置和內容。經過壓縮之後,原來需要宣告大小為63的陣列,而使用壓縮後,只需要宣告大小為6
3的陣列,僅需18個儲存空間

繼續閱讀SparseArray的原始碼,從構造方法我們可以看出,它和一般的List一樣,可以預先設定容器大小,預設的大小是10:

 public SparseArray() {
        this(10);
    }

注意事項

SparseArray是android裡為<Interger,Object>這樣的Hashmap而專門寫的類,目的是提高記憶體效率,其核心是折半查詢函式(binarySearch)。注意記憶體二字很重要,因為它僅僅提高記憶體效率,而不是提高執行效率,
它只適用於android系統(記憶體對android專案有多重要,地球人都知道)。SparseArray有兩個優點:1.避免了自動裝箱(auto-boxing),2.資料結構不會依賴於外部物件對映。我們知道HashMap 採用一種所謂的“Hash 演算法”來決定每個元素的儲存位置,存放的都是陣列元素的引用,通過每個物件的hash值來對映物件。而SparseArray則是用陣列資料結構來儲存對映,然後通過折半查詢來找到物件。但其實一般來說,SparseArray執行效率比HashMap要慢一點,因為查詢需要折半查詢,而新增刪除則需要在陣列中執行,而HashMap都是通過外部對映。但相對來說影響不大,最主要是SparseArray不需要開闢記憶體空間來額外儲存外部對映,從而節省記憶體

相關文章