首先說一下SparseArray是什麼東西,在java中咱們也沒見過這個API啊,哦,原來是android中定義的一個類,按字面意思來講是一個稀疏數組,但經過源碼註釋咱們發現它和數組有很大的區別:
java
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.
咱們經過這段註釋大致知道,android但願咱們用SparseArray在一些狀況下代替HashMap來使用,由於它有更好的性能,你們都知道內存是很是寶貴的,尤爲是在手機上。android
再看一下它的兩個構造函數:
數組
/** * Creates a new SparseArray containing no mappings. */ public SparseArray() { this(10); } /** * Creates a new SparseArray containing no mappings that will not * require any additional memory allocation to store the specified * number of mappings. If you supply an initial capacity of 0, the * sparse array will be initialized with a light-weight representation * not requiring any additional array allocations. */ public SparseArray(int initialCapacity) { if (initialCapacity == 0) { mKeys = EmptyArray.INT; mValues = EmptyArray.OBJECT; } else { mValues = ArrayUtils.newUnpaddedObjectArray(initialCapacity); mKeys = new int[mValues.length]; } mSize = 0; }
發現其默認的key-value數組大小是10,固然也能夠是自定義的。app
SparseArray中有一些和HashMap中類似的實用方法,好比:函數
put(int key, E value) get(int key) get(int key, E valueIfKeyNotFound) delete(int key) removeAt(int index) keyAt(int index) valueAt(int index) 等等。
隨便分析一個方法,好比put(int key,E value):性能
/** * Adds a mapping from the specified key to the specified value, * replacing the previous mapping from the specified key if there * was one. */ public void put(int key, E value) { int i = ContainerHelpers.binarySearch(mKeys, 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 = ~ContainerHelpers.binarySearch(mKeys, mSize, key); } mKeys = GrowingArrayUtils.insert(mKeys, mSize, i, key); mValues = GrowingArrayUtils.insert(mValues, mSize, i, value); mSize++; } }
代碼中首先查詢該key在SparseArray中是否已經存在,若存在,替換掉,若不存在,把對應的key和value插入到對應的數組中,而後mSize++。你們注意到在查詢key時使用的折半查找,看源碼:ui
class ContainerHelpers { // This is Arrays.binarySearch(), but doesn't do any argument validation. static int binarySearch(int[] array, int size, int value) { int lo = 0; int hi = size - 1; while (lo <= hi) { final int mid = (lo + hi) >>> 1; final int midVal = array[mid]; if (midVal < value) { lo = mid + 1; } else if (midVal > value) { hi = mid - 1; } else { return mid; // value found } } return ~lo; // value not present } static int binarySearch(long[] array, int size, long value) { int lo = 0; int hi = size - 1; while (lo <= hi) { final int mid = (lo + hi) >>> 1; final long midVal = array[mid]; if (midVal < value) { lo = mid + 1; } else if (midVal > value) { hi = mid - 1; } else { return mid; // value found } } return ~lo; // value not present } }
哇哦,是否是咱們在java中經常使用的一種查找方式。this
知道了這些以後,咱們之後就可使用SparseArray來代替HashMap了,可是要注意SparseArray中的key是int類型,若實際中不是int類型,還得乖乖的使用map,另外,根據key-value中的value類型不一樣,android又給封裝了SparseIntArray,SparseBooleanArray,SparseLongArray等等,使用方法和SparseArray都大同小異,只要你會使用Map,那麼你就會使用SparseArray。spa