转载

每日一博 |SparseArray 介绍

首先说一下SparseArray是什么东西,在java中我们也没见过这个API啊,哦,原来是android中定义的一个类,按字面意思来说是一个稀疏数组,但通过源码注释我们发现它和数组有很大的区别:

 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来使用,因为它有更好的性能,大家都知道内存是非常宝贵的,尤其是在手机上。

再看一下它的两个构造函数:

/**  * 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,当然也可以是自定义的。

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时使用的折半查找,看源码:

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中常用的一种查找方式。

知道了这些之后,我们以后就可以使用SparseArray来代替HashMap了,但是要注意SparseArray中的key是int类型,若实际中不是int类型,还得乖乖的使用map,另外,根据key-value中的value类型不同,android又给封装了SparseIntArray,SparseBooleanArray,SparseLongArray等等,使用方法和SparseArray都大同小异,只要你会使用Map,那么你就会使用SparseArray。

原文  http://my.oschina.net/gef/blog/600698?fromerr=BMJwUI1v
正文到此结束
Loading...