Android4.4之后推出的ArrayMap集合詳解

通常我們?cè)谑褂胟ey-value存儲(chǔ)數(shù)據(jù)時(shí)买决,隨手就會(huì)打出HashMap的代碼,當(dāng)數(shù)據(jù)量較小時(shí)带猴,還可以昔汉,當(dāng)數(shù)量比較多的時(shí)候,如果是PC機(jī)上拴清,也還說(shuō)得過(guò)去靶病,但是如果使用設(shè)備是手機(jī)等移動(dòng)設(shè)備,這是就要慎重了口予。因?yàn)槭謾C(jī)的內(nèi)存非常寶貴娄周,不像PC那樣不計(jì)后果的使用,內(nèi)存使用不當(dāng)很容易就會(huì)引起OOM的問(wèn)題沪停。那Android開發(fā)團(tuán)隊(duì)煤辨,也為我們找到了HashMap的替代品ArrayMap。

官方對(duì)ArrayMap也有說(shuō)明:它不是一個(gè)適應(yīng)大數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)木张,相比傳統(tǒng)的HashMap速度要慢众辨,因?yàn)椴檎曳椒ㄊ嵌址ǎ⑶耶?dāng)你刪除或者添加數(shù)據(jù)時(shí)窟哺,會(huì)對(duì)空間重新調(diào)整泻轰,在使用大量數(shù)據(jù)時(shí),效率并不明顯且轨,低于50%浮声。

所以ArrayMap是犧牲了時(shí)間換區(qū)空間。在寫手機(jī)app時(shí)旋奢,適時(shí)的使用ArrayMap泳挥,會(huì)給內(nèi)存使用帶來(lái)可觀的提升。

那HashMap和ArrayMap到底不同在哪呢至朗,個(gè)人總結(jié)有以下方面:

1屉符、存儲(chǔ)方式不同。

HashMap內(nèi)部有一個(gè)HashMapEntry[]對(duì)象,每一個(gè)鍵值對(duì)都存儲(chǔ)在這個(gè)對(duì)象里矗钟,當(dāng)使用put方法添加鍵值對(duì)時(shí)唆香,就會(huì)new一個(gè)HashMapEntry對(duì)象

[java]view plaincopy

@OverridepublicV?put(K?key,?V?value)?{

if(key?==null)?{

returnputValueForNullKey(value);

}

inthash?=?secondaryHash(key);

HashMapEntry[]?tab?=?table;

intindex?=?hash?&?(tab.length?-1);

//先查找有沒(méi)有對(duì)應(yīng)的key值,如果有吨艇,就改寫value躬它,并返回改寫前的value值:oldValue

for(HashMapEntry?e?=?tab[index];?e?!=null;?e?=?e.next)?{

if(e.hash?==?hash?&&?key.equals(e.key))?{

preModify(e);

V?oldValue?=?e.value;

e.value?=?value;

returnoldValue;

}

}

//?No?entry?for?(non-null)?key?is?present;?create?one

modCount++;

if(size++?>?threshold)?{

//擴(kuò)容,雙倍

tab?=?doubleCapacity();

index?=?hash?&?(tab.length?-1);

}

addNewEntry(key,?value,?hash,?index);

returnnull;

}

//創(chuàng)建對(duì)象存儲(chǔ)鍵值對(duì)

voidaddNewEntry(K?key,?V?value,inthash,intindex)?{

table[index]?=newHashMapEntry(key,?value,?hash,?table[index]);

}

ArrayMap的存儲(chǔ)中沒(méi)有Entry這個(gè)東西东涡,他是由兩個(gè)數(shù)組來(lái)維護(hù)的

[java]view plaincopy

int[]?mHashes;

Object[]?mArray;

mHashes數(shù)組中保存的是每一項(xiàng)的HashCode值冯吓,mArray中就是鍵值對(duì),每?jī)蓚€(gè)元素代表一個(gè)鍵值對(duì)疮跑,前面保存key组贺,后面的保存value,我們看看下面代碼的結(jié)果

[java]view plaincopy

arraymap?=newHashMap();

a.put("a","a_value");

a.put("b","b_value");

執(zhí)行上面代碼后祖娘,arraymap中的存儲(chǔ)是這樣的

是不是能清楚地看到ArrayMap的存儲(chǔ)了失尖,這種存儲(chǔ)在put代碼中如下

[java]view plaincopy

mHashes[index]?=?hash;

mArray[index<<1]?=?key;

mArray[(index<<1)+1]?=?value;

2、添加數(shù)據(jù)時(shí)擴(kuò)容時(shí)的處理不一樣

先來(lái)看看HashMap

[java]view plaincopy

if(size++?>?threshold)?{

tab?=?doubleCapacity();

index?=?hash?&?(tab.length?-1);

}

doubleCapacity進(jìn)行雙倍擴(kuò)容贿条,它的代碼中有這么一句話

[java]view plaincopy

HashMapEntry[]?newTable?=?makeTable(newCapacity);

最終雹仿,這個(gè)newTable將作為擴(kuò)容后的新對(duì)象返回,那么makeTable做了什么呢整以,如下:

[java]view plaincopy

privateHashMapEntry[]?makeTable(intnewCapacity)?{

@SuppressWarnings("unchecked")?HashMapEntry[]?newTable

=?(HashMapEntry[])newHashMapEntry[newCapacity];

table?=?newTable;

threshold?=?(newCapacity?>>1)?+?(newCapacity?>>2);//?3/4?capacity

returnnewTable;

}

我們清楚地看到胧辽,這里進(jìn)行了new操作,重新創(chuàng)建對(duì)象公黑,開銷很大邑商。

那么ArrayMap呢,看看吧

[java]view plaincopy

//如果容量不夠

ize?>=?mHashes.length)?{

finalintn?=?mSize?>=?(BASE_SIZE*2)???(mSize+(mSize>>1))

:?(mSize?>=?BASE_SIZE???(BASE_SIZE*2)?:?BASE_SIZE);

if(DEBUG)?Log.d(TAG,"put:?grow?from?"+?mHashes.length?+"?to?"+?n);

finalint[]?ohashes?=?mHashes;

finalObject[]?oarray?=?mArray;

//分配數(shù)組

allocArrays(n);

if(mHashes.length?>0)?{

if(DEBUG)?Log.d(TAG,"put:?copy?0-"+?mSize?+"?to?0");

//特別注意這凡蚜,是copy人断,而不是new,效率提升

System.arraycopy(ohashes,0,?mHashes,0,?ohashes.length);

System.arraycopy(oarray,0,?mArray,0,?oarray.length);

}

//釋放無(wú)用空間朝蜘,收縮數(shù)組

freeArrays(ohashes,?oarray,?mSize);

}

ArrayMap用的是copy數(shù)據(jù)恶迈,所以效率相對(duì)要高。

3谱醇、ArrayMap提供了數(shù)組收縮的功能暇仲,在clear或remove后,會(huì)重新收縮數(shù)組副渴,是否空間

4奈附、ArrayMap采用二分法查找(見 android.support.v4.util.ContainerHelpers中的binarySearch方法)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市煮剧,隨后出現(xiàn)的幾起案子斥滤,更是在濱河造成了極大的恐慌将鸵,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,194評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件佑颇,死亡現(xiàn)場(chǎng)離奇詭異顶掉,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)漩符,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門一喘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人嗜暴,你說(shuō)我怎么就攤上這事∫轶。” “怎么了闷沥?”我有些...
    開封第一講書人閱讀 156,780評(píng)論 0 346
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)咐容。 經(jīng)常有香客問(wèn)我舆逃,道長(zhǎng),這世上最難降的妖魔是什么戳粒? 我笑而不...
    開封第一講書人閱讀 56,388評(píng)論 1 283
  • 正文 為了忘掉前任路狮,我火速辦了婚禮,結(jié)果婚禮上蔚约,老公的妹妹穿的比我還像新娘奄妨。我一直安慰自己,他們只是感情好苹祟,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評(píng)論 5 384
  • 文/花漫 我一把揭開白布砸抛。 她就那樣靜靜地躺著,像睡著了一般树枫。 火紅的嫁衣襯著肌膚如雪直焙。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,764評(píng)論 1 290
  • 那天砂轻,我揣著相機(jī)與錄音奔誓,去河邊找鬼。 笑死搔涝,一個(gè)胖子當(dāng)著我的面吹牛厨喂,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播体谒,決...
    沈念sama閱讀 38,907評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼杯聚,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了抒痒?” 一聲冷哼從身側(cè)響起幌绍,我...
    開封第一講書人閱讀 37,679評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后傀广,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體颁独,經(jīng)...
    沈念sama閱讀 44,122評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評(píng)論 2 325
  • 正文 我和宋清朗相戀三年伪冰,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了誓酒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,605評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡贮聂,死狀恐怖靠柑,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情吓懈,我是刑警寧澤歼冰,帶...
    沈念sama閱讀 34,270評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站耻警,受9級(jí)特大地震影響隔嫡,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜甘穿,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評(píng)論 3 312
  • 文/蒙蒙 一腮恩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧温兼,春花似錦秸滴、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至兰伤,卻和暖如春内颗,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背敦腔。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工均澳, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人符衔。 一個(gè)月前我還...
    沈念sama閱讀 46,297評(píng)論 2 360
  • 正文 我出身青樓找前,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親判族。 傳聞我的和親對(duì)象是個(gè)殘疾皇子躺盛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評(píng)論 2 348

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

  • 一槽惫、基本數(shù)據(jù)類型 注釋 單行注釋:// 區(qū)域注釋:/* */ 文檔注釋:/** */ 數(shù)值 對(duì)于byte類型而言...
    龍貓小爺閱讀 4,257評(píng)論 0 16
  • 背景 一年多以前我在知乎上答了有關(guān)LeetCode的問(wèn)題, 分享了一些自己做題目的經(jīng)驗(yàn)周叮。 張土汪:刷leetcod...
    土汪閱讀 12,737評(píng)論 0 33
  • 宣堡,又稱宣家堡界斜;在宣堡郊區(qū)仿耽,聳立著一個(gè)巍峨高大的牌匾刻著“宣家堡”;我的那個(gè)他用地道的方言告訴我各薇,叫“宣嘎堡”项贺。...
    三末閱讀 458評(píng)論 0 1
  • 這本書其實(shí)是讓我有些失望的开缎,也有可能是期望過(guò)高了些。 其實(shí)在看《挪威的森林》時(shí)林螃,盡管故事講述的是主角渡邊糾纏在情緒...
    七筒妹妹閱讀 749評(píng)論 0 0
  • 生活是件細(xì)碎的事 在千千細(xì)碎中是否有一片是我對(duì)你的牽掛 是否有一種羈絆在你碌碌中沉寂 又在某個(gè)午夜夢(mèng)回時(shí)給你清醒的...
    南方的茶閱讀 164評(píng)論 0 0