Android應(yīng)用性能優(yōu)化之使用SparseArray替代HashMap

注意:SparseArray<Object>對(duì)應(yīng)的是HashMap<Integer,Object>官还,如果是HashMap<String,Object>等則無(wú)法代替穴张;SparseArray只能優(yōu)化內(nèi)存(意譯即為稀疏數(shù)組)鲁猩,并不能優(yōu)化存取速度腾供;采用二分查找來(lái)查找key,會(huì)頻繁的插入遮怜、刪除實(shí)體(entry)到數(shù)組里淋袖,所以比起Hashmap速度并沒(méi)有明顯提升;

HashMap是java里比較常用的一個(gè)集合類(lèi)锯梁,我比較習(xí)慣用來(lái)緩存一些處理后的結(jié)果适贸。最近在做一個(gè)Android項(xiàng)目,在代碼中定義這樣一個(gè)變量涝桅,實(shí)例化時(shí)拜姿,Eclipse卻給出了一個(gè) performance 警告。

sparsearray

意思就是說(shuō)用SparseArray 來(lái)替代冯遂,以獲取更好性能蕊肥。老實(shí)說(shuō),對(duì)SparseArray并不熟悉蛤肌,第一感覺(jué)應(yīng)該是Android提供的一個(gè)類(lèi)壁却。按住Ctrl點(diǎn)擊進(jìn)入SparseArray的源碼,果不其然裸准,確定是Android提供的一個(gè)工具類(lèi)展东。

android_util_sparsearray

單純從字面上來(lái)理解,SparseArray指的是稀疏數(shù)組(Sparse array)炒俱,所謂稀疏數(shù)組就是數(shù)組中大部分的內(nèi)容值都未被使用(或都為零)盐肃,在數(shù)組中僅有少部分的空間使用。因此造成內(nèi)存空間的浪費(fèi)权悟,為了節(jié)省內(nèi)存空間砸王,并且不影響數(shù)組中原有的內(nèi)容值,我們可以采用一種壓縮的方式來(lái)表示稀疏數(shù)組的內(nèi)容峦阁。

假設(shè)有一個(gè)9*7的數(shù)組谦铃,其內(nèi)容如下:

sparsearray_pic1

在此數(shù)組中,共有63個(gè)空間榔昔,但卻只使用了5個(gè)元素驹闰,造成58個(gè)元素空間的浪費(fèi)瘪菌。以下我們就使用稀疏數(shù)組重新來(lái)定義這個(gè)數(shù)組:

sparsearray_pic2.jpg

其中在稀疏數(shù)組中第一部分所記錄的是原數(shù)組的列數(shù)和行數(shù)以及元素使用的個(gè)數(shù)、第二部分所記錄的是原數(shù)組中元素的位置和內(nèi)容嘹朗。經(jīng)過(guò)壓縮之后师妙,原來(lái)需要聲明大小為63的數(shù)組,而使用壓縮后骡显,只需要聲明大小為6*3的數(shù)組,僅需18個(gè)存儲(chǔ)空間曾掂。

繼續(xù)閱讀SparseArray的源碼惫谤,從構(gòu)造方法我們可以看出,它和一般的List一樣珠洗,可以預(yù)先設(shè)置容器大小溜歪,默認(rèn)的大小是10:

publicSparseArray(){

this(10);

}

publicSparseArray(intinitialCapacity){

initialCapacity=ArrayUtils.idealIntArraySize(initialCapacity);

mKeys=newint[initialCapacity];

mValues=newObject[initialCapacity];

mSize=0;

}

再來(lái)看看它對(duì)數(shù)據(jù)的”增刪改查”。

它有兩個(gè)方法可以添加鍵值對(duì):

publicvoidput(intkey,E value){}

publicvoidappend(intkey,E value){}

有四個(gè)方法可以執(zhí)行刪除操作:

publicvoiddelete(intkey){}

publicvoidremove(intkey){}//直接調(diào)用的delete(int key)

publicvoidremoveAt(intindex){}

publicvoidclear(){}

修改數(shù)據(jù)起初以為只有setValueAt(int index, E value)可以修改數(shù)據(jù)许蓖,但后來(lái)發(fā)現(xiàn)put(int key, E value)也可以修改數(shù)據(jù)蝴猪,我們查看put(int key, E value)的源碼可知,在put數(shù)據(jù)之前膊爪,會(huì)先查找要put的數(shù)據(jù)是否已經(jīng)存在自阱,如果存在就是修改,不存在就添加米酬。

publicvoidput(intkey,E value){

inti=binarySearch(mKeys,0,mSize,key);

if(i>=0){

mValues[i]=value;

}else{

i=~i;

if(i

mKeys[i]=key;

mValues[i]=value;

return;

}

if(mGarbage&&mSize>=mKeys.length){

gc();

// Search again because indices may have changed.

i=~binarySearch(mKeys,0,mSize,key);

}

…………

所以沛豌,修改數(shù)據(jù)實(shí)際也有兩種方法:

publicvoidput(intkey,E value)

publicvoidsetValueAt(intindex,E value)

最后再來(lái)看看如何查找數(shù)據(jù)。有兩個(gè)方法可以查詢(xún)?nèi)≈担?/p>

publicEget(intkey)

publicEget(intkey,E valueIfKeyNotFound)

其中g(shù)et(int key)也只是調(diào)用了 get(int key,E valueIfKeyNotFound),最后一個(gè)從傳參的變量名就能看出赃额,傳入的是找不到的時(shí)候返回的值.get(int key)當(dāng)找不到的時(shí)候加派,默認(rèn)返回null。

查看第幾個(gè)位置的鍵:public int keyAt(int index)

有一點(diǎn)需要注意的是跳芳,查看鍵所在位置芍锦,由于是采用二分法查找鍵的位置,所以找不到時(shí)返回小于0的數(shù)值飞盆,而不是返回-1娄琉。返回的負(fù)值是表示它在找不到時(shí)所在的位置。

查看第幾個(gè)位置的值:

public E valueAt(int index)

查看值所在位置吓歇,沒(méi)有的話(huà)返回-1:

public int indexOfValue(E value)

最后车胡,發(fā)現(xiàn)其核心就是折半查找函數(shù)(binarySearch),算法設(shè)計(jì)的很不錯(cuò)照瘾。

privatestaticintbinarySearch(int[]a,intstart,intlen,intkey){

inthigh=start+len,low=start-1,guess;

while(high-low>1){

guess=(high+low)/2;

if(a[guess]

low=guess;

else

high=guess;

}

if(high==start+len)

return~(start+len);

elseif(a[high]==key)

returnhigh;

else

return~high;

}

相應(yīng)的也有SparseBooleanArray匈棘,用來(lái)取代HashMap ,SparseIntArray用來(lái)取代HashMap 析命,大家有興趣的可以研究主卫。

總結(jié):

SparseArray是android里為這樣的Hashmap而專(zhuān)門(mén)寫(xiě)的類(lèi),目的是提高效率逃默,其核心是折半查找函數(shù)(binarySearch)。在Android中簇搅,當(dāng)我們需要定義

HashMap hashMap = new HashMap ();

時(shí)完域,我們可以使用如下的方式來(lái)取得更好的性能.

SparseArray sparseArray = new SparseArray ();

https://liuzhichao.com/p/832.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市瘩将,隨后出現(xiàn)的幾起案子吟税,更是在濱河造成了極大的恐慌,老刑警劉巖姿现,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件肠仪,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡备典,警方通過(guò)查閱死者的電腦和手機(jī)异旧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)提佣,“玉大人吮蛹,你說(shuō)我怎么就攤上這事“杵粒” “怎么了潮针?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀(guān)的道長(zhǎng)倚喂。 經(jīng)常有香客問(wèn)我然低,道長(zhǎng),這世上最難降的妖魔是什么务唐? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任雳攘,我火速辦了婚禮,結(jié)果婚禮上枫笛,老公的妹妹穿的比我還像新娘吨灭。我一直安慰自己,他們只是感情好刑巧,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布喧兄。 她就那樣靜靜地躺著,像睡著了一般啊楚。 火紅的嫁衣襯著肌膚如雪吠冤。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,146評(píng)論 1 297
  • 那天恭理,我揣著相機(jī)與錄音拯辙,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛涯保,可吹牛的內(nèi)容都是我干的诉濒。 我是一名探鬼主播,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼夕春,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼未荒!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起及志,我...
    開(kāi)封第一講書(shū)人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤片排,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后速侈,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體率寡,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年锌畸,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了勇劣。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片靖避。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡潭枣,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出幻捏,到底是詐尸還是另有隱情盆犁,我是刑警寧澤,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布篡九,位于F島的核電站谐岁,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏榛臼。R本人自食惡果不足惜伊佃,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望沛善。 院中可真熱鬧航揉,春花似錦、人聲如沸金刁。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)尤蛮。三九已至媳友,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間产捞,已是汗流浹背醇锚。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留坯临,地道東北人搂抒。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓艇搀,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親求晶。 傳聞我的和親對(duì)象是個(gè)殘疾皇子焰雕,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353

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