HashMap can be replaced with SparseArray--Android应用性能优化之使用SparseArray替代HashMap
HashMap是java里比較常用的一個(gè)集合類,我比較習(xí)慣用來緩存一些處理后的結(jié)果。最近在做一個(gè)Android項(xiàng)目,在代碼中定義這樣一個(gè)變量,實(shí)例化時(shí),Eclipse卻給出了一個(gè) performance 警告。
意思就是說用SparseArray <E>?來替代,以獲取更好性能。老實(shí)說,對(duì)SparseArray并不熟悉,第一感覺應(yīng)該是Android提供的一個(gè)類。按住Ctrl點(diǎn)擊進(jìn)入SparseArray的源碼,果不其然,確定是Android提供的一個(gè)工具類。
單純從字面上來理解,SparseArray指的是稀疏數(shù)組(Sparse array)?,所謂稀疏數(shù)組就是數(shù)組中大部分的內(nèi)容值都未被使用(或都為零),在數(shù)組中僅有少部分的空間使用。因此造成內(nèi)存空間的浪費(fèi),為了節(jié)省內(nèi)存空間,并且不影響數(shù)組中原有的內(nèi)容值,我們可以采用一種壓縮的方式來表示稀疏數(shù)組的內(nèi)容。
假設(shè)有一個(gè)9*7的數(shù)組,其內(nèi)容如下:
其中在稀疏數(shù)組中第一部分所記錄的是原數(shù)組的列數(shù)和行數(shù)以及元素使用的個(gè)數(shù)、第二部分所記錄的是原數(shù)組中元素的位置和內(nèi)容。經(jīng)過壓縮之后,原來需要聲明大小為63的數(shù)組,而使用壓縮后,只需要聲明大小為6*3的數(shù)組,僅需18個(gè)存儲(chǔ)空間。
繼續(xù)閱讀SparseArray的源碼,從構(gòu)造方法我們可以看出,它和一般的List一樣,可以預(yù)先設(shè)置容器大小,默認(rèn)的大小是10:
public SparseArray() {this(10);}public SparseArray(int initialCapacity) {initialCapacity = ArrayUtils.idealIntArraySize(initialCapacity);mKeys = new int[initialCapacity];mValues = new Object[initialCapacity];mSize = 0;}再來看看它對(duì)數(shù)據(jù)的“增刪改查”。
(1)它有兩個(gè)方法可以添加鍵值對(duì):
public void put(int key, E value) {}public void append(int key, E value){}(2)有四個(gè)方法可以執(zhí)行刪除操作:
public void delete(int key) {}public void remove(int key) {} //直接調(diào)用的delete(int key)public void removeAt(int index){}public void clear(){}
(3)修改操作 修改數(shù)據(jù)起初以為只有setValueAt(int index, E value)可以修改數(shù)據(jù),但后來發(fā)現(xiàn)put(int key, E value)也可以修改數(shù)據(jù),我們查看put(int key, E value)的源碼可知,在put數(shù)據(jù)之前,會(huì)先查找要put的數(shù)據(jù)是否已經(jīng)存在,如果存在就是修改,不存在就添加。
public void put(int key, E value) {int i = binarySearch(mKeys, 0, mSize, key);if (i > = 0) {mValues[i] = value;} else {i = ~i;if (i < mSize && mValues[i] == DELETED) {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í)際也有兩種方法: public void put(int key, E value)public void setValueAt(int index, E value)
(4)最后再來看看如何查找數(shù)據(jù)。有兩個(gè)方法可以查詢?nèi)≈?#xff1a;
public E get(int key)public E get(int key, 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)
查看值所在位置,沒有的話返回-1:
public int indexOfValue(E value)
最后,發(fā)現(xiàn)其核心就是折半查找函數(shù)(binarySearch),算法設(shè)計(jì)的很不錯(cuò)。
相應(yīng)的也有SparseBooleanArray,用來取代HashMap <Integer, Boolean>?,SparseIntArray用來取代HashMap <Integer, Integer>?,大家有興趣的可以研究。
總結(jié):
SparseArray是android里為<Interger,Object>?這樣的Hashmap而專門寫的類,目的是提高效率,其核心是折半查找函數(shù)(binarySearch)。在Android中,當(dāng)我們需要定義
HashMap <Integer, E> hashMap = new HashMap <Integer, E> ();
時(shí),我們可以使用如下的方式來取得更好的性能.
SparseArray <E> sparseArray = new SparseArray <E> ();
=====================
SparseArray
extends?Objectimplements?Cloneable
| java.lang.Object | |
| ???? | android.util.SparseArray<E> |
Class Overview
SparseArrays map integers to Objects. Unlike a normal array of Objects, there can be gaps in the indices. It is intended to be more memory efficient than using a HashMap to map Integers to Objects, both because it avoids auto-boxing keys and its data structure doesn't rely on an extra entry object for each mapping.
Note that this container keeps its mappings in an array data structure, using a binary search to find keys.The implementation is not intended to be appropriate for data structures that may contain large numbers of items.It is generally slower than a traditional HashMap, since lookups require a binary search and adds and removes require inserting and deleting entries in the array. For containers holding up to hundreds of items, the performance difference is not significant, less than 50%.
To help with performance, the container includes an optimization when removing keys: instead of compacting its array immediately, it leaves the removed entry marked as deleted. The entry can then be re-used for the same key, or compacted later in a single garbage collection step of all removed entries. This garbage collection will need to be performed at any time the array needs to be grown or the the map size or entry values are retrieved.
It is possible to iterate over the items in this container using?keyAt(int)?and?valueAt(int). Iterating over the keys using?keyAt(int)?with values of the index will return the keys in ascending order, or the values corresponding to the keys in ascending order in the case of?valueAt(int).
摘自:http://developer.android.com/reference/android/util/SparseArray.html
總結(jié)
以上是生活随笔為你收集整理的HashMap can be replaced with SparseArray--Android应用性能优化之使用SparseArray替代HashMap的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于Adapter的The conten
- 下一篇: Android 那些你所不知道的Bitm