SparseArray和ArrayMap的內部實現

2021-08-29 04:45:12 字數 2851 閱讀 5151

1、sparsearray

上面這段話來自sparsearray類的宣告,重點關注一下: 與使用hashmap將integers對映到objects相比,它的記憶體效率更高,因為它避免了自動裝箱鍵,並且其資料結構不依賴於每個對映的額外條目物件。(這也是sparsearray的優點)

sparsearray包含三個主要成員變數:

private int mkeys;

private object mvalues;

private int msize;

其中,mkeys用於存放鍵key,mvalues用來存放值(泛型e)。msize為鍵值對的數量。

初始容量預設為10。

先看put方法:

public void put(int key, e value)  else 

if (mgarbage && msize >= mkeys.length)

mkeys = growingarrayutils.insert(mkeys, msize, i, key);

mvalues = growingarrayutils.insert(mvalues, msize, i, value);

msize++;

}}

put方法首先在mkeys陣列中通過二分查詢演算法,找到key在mkeys陣列中的索引 i,如果i>0,即已經存在乙個鍵值對,則直接覆蓋mvalues陣列中的值。如果i<0,即不存在該鍵值對,但是由於mkeys陣列是從小到大排好序的,-i為key需要插入mkeys陣列中的位置,並且mkeys和mvalues陣列還有剩餘空間並且-i索引位置的值為空,表示不需要擴容並且不需要資料遷移,則把key存放在mkeys陣列的-i索引位置,value存放在mvalues陣列-i索引位置。

public static long insert(long array, int currentsize, int index, long element) 

long newarray = arrayutils.newunpaddedlongarray(growsize(currentsize));

system.arraycopy(array, 0, newarray, 0, index);

newarray[index] = element;

system.arraycopy(array, index, newarray, index + 1, array.length - index);

return newarray;

}

如果,當前mkeys陣列和mvalues陣列已滿,或者-i索引位置已經有值。則通過growingarrayutils.insert方法把key插入到-i索引位置,並將-i(包含)以後的key向後平移乙個單位來完成key遷移。如果mkeys陣列需要擴容,則呼叫growingarrayutils.growsize方法進行擴容

public static int growsize(int currentsize)
擴容規則為:當前容量不大於4時直接擴容到8,否則雙倍擴容,由於前面說過初始容量為10,所以都是雙倍擴容。擴容完成後,在完成上面的key遷移過程。

再看get方法

public e get(int key) 

public e get(int key, e valueifkeynotfound) else

}

很簡單,直接通過二分查詢在mkeys陣列中找到對應的索引,如果索引存在則直接返回mvalues陣列中該索引下的值。否則返回null。

2、arraymap

int mhashes;

object marray;

int msize;

arraymap同樣也是三個重要成員變數:1,mhashes用於存放key物件的hashcode值,該值也按照從小到大的順序排序。2,marray用於存放key和value物件。具提存放策略稍後講。3,msize為key-value鍵值對的數量。
同樣先看put方法

@override

public v put(k key, v value) else

if (index >= 0)

index = ~index;

if (osize >= mhashes.length)

if (mhashes.length > 0)

freearrays(ohashes, oarray, osize);

}if (index < osize)

if (concurrent_modification_exceptions)

}mhashes[index] = hash;

marray[index<<1] = key;

marray[(index<<1)+1] = value;

msize++;

return null;

}

從上面可以看出,put方法先判斷key是否為空,如果為空,則hashcode為0,否則獲取key的hashcode值,然後根據hashcode值在mkeys陣列中找到對應的索引index,如果index>=0,則在marray陣列中2*index索引位置存放key物件,2*index+1索引位置存放value物件。如果index<0,表示沒找到則-index為當前hashcode要插入到mkeys陣列中的位置。如果mhashes陣列需要擴容,則判斷當前msize是否大於等於8(base_size*2),如果是則擴容為原來的1.5倍,否則判斷msize是否大於等於4,如果是則擴容為8,否則擴容為4。擴容完成後,將資料遷移到新的陣列中。

get方法與sparsearray差不多。

SparseArray擴容機制

sparsearray指的是稀疏陣列,就是陣列中並沒有填滿,只有部分有值,這樣造成了記憶體浪費,往往採用的是壓縮的方式來儲存內容。了解下sparsearray怎麼儲存的以及sparsearray的擴容。看下 public class sparsearrayimplements cloneable p...

稀疏sparsearray陣列

將二維陣列轉成稀疏陣列 1.先遍歷二維陣列 得到非0資料的個數 int sum 0 for int i 0 i 11 i system.out.println sum sum 建立對應的稀疏陣列 int sparsearr new int sum 1 3 給稀疏陣列賦值 sparsearr 0 0 ...

稀疏sparsearray陣列

線性結構常見的有 陣列 佇列 鍊錶和棧 非線性結構包括 二維陣列 多維陣列 廣義表 樹結構 圖結構 編寫的五子棋程式中,有存檔退出和續上盤的功能 分析問題 因為該二維陣列的很多值是預設值 0,因此記錄了很多沒有意義的資料 稀疏陣列。當乙個陣列中大部分元素為 或者為同乙個值的陣列時,可以使用稀疏陣列來...