Android 移动端数据结构

## SparseArray 

## SparseBooleanArray

## SparseIntArray

## SparseLongArray

* 位于android.util,Android 中的数据结构,针对移动端做了优化,在数据量比较少的情况下,性能会好过 HashMap,类似于 HashMap,key:int ,value:object 。

* 为什么性能会好:

1. key  和 value  采用数组进行存储。存储 key 的数组是 int 类型,不需要进行装箱操作。提供了速度。

2. 采用二分查找法,在插入进行了排序,所以两个数组是按照从小到大进行排序的。

3. 在查找的时候,进行二分查找,数据量少的情况下,速度比较快。

同时还有一个类:SparseArrayCompat,位于android.support.v4.util,与 SparseArray 一样的。

其中有好几个类似的数据结构:SparseBooleanArray(key:int, value:boolean), SparseIntArray(key:int, value:int), SparseLongArray(key:int, value:long). SparseArray 通过数组对 key , value 进行存储。

在 map Integers to Objects 方面进行了优化,所以比使用 HashMap 提高了性能,建议遇到key:int, value:object 的情况下使用。

构造方法:

默认构造方法中会创建长度为 10 的数组来分别储存 key 和 value。

可以自己在手动输入一个数字,来创建一个指定长度的数组来存储key 和 value。

增:

public void put(int key, E value)  // 存储指定key 和指定value ,假如指定key 已经有了在映射中,替换掉已经存在的。
public void append(int key, E value) // 储存 key value 到数组,key 的索引应该大于数组中的已有索引

删:

public void delete(int key)  // 删除指定key
public void remove(int key)  // 调用 delete 方法
public void removeAt(int index) // 删除指定索引
public void removeAtRange(int index, int size) //删除指定范围的索引
public void clear()  //清空所有内容

改:

public void put(int key, E value)  // 指定key 已存在的情况下,更新,不存在的情况下,增加
public void setValueAt(int index, E value) // 更新指定索引的 value

查:

public E get(int key)   // 得到指定key 的 value,调用的是 get(int key, null)
public E get(int key, E valueIfKeyNotFound) // 返回指定key 的value,没有的情况下,返回传入的默认值
public int indexOfKey(int key) // 传入key 的索引
public int indexOfValue(E value) // 传入 value 的索引
public int keyAt(int index) // 指定索引的 key
public E valueAt(int index) //指定索引的 value

 

源码:

  1 public class SparseArray<E> implements Cloneable {
  2     private static final Object DELETED = new Object();
  3     private boolean mGarbage = false;
  4 
  5     private int[] mKeys;
  6     private Object[] mValues;
  7     private int mSize;
  8 
  9     /**
 10      * Creates a new SparseArray containing no mappings.
 11      */
 12     public SparseArray() {
 13         this(10);
 14     }
 15 
 16     /**
 17      * Creates a new SparseArray containing no mappings that will not
 18      * require any additional memory allocation to store the specified
 19      * number of mappings.  If you supply an initial capacity of 0, the
 20      * sparse array will be initialized with a light-weight representation
 21      * not requiring any additional array allocations.
 22      */
 23     public SparseArray(int initialCapacity) {
 24         if (initialCapacity == 0) {
 25             mKeys = EmptyArray.INT;
 26             mValues = EmptyArray.OBJECT;
 27         } else {
 28             mValues = ArrayUtils.newUnpaddedObjectArray(initialCapacity);
 29             mKeys = new int[mValues.length];
 30         }
 31         mSize = 0;
 32     }
 33 
 34     @Override
 35     @SuppressWarnings("unchecked")
 36     public SparseArray<E> clone() {
 37         SparseArray<E> clone = null;
 38         try {
 39             clone = (SparseArray<E>) super.clone();
 40             clone.mKeys = mKeys.clone();
 41             clone.mValues = mValues.clone();
 42         } catch (CloneNotSupportedException cnse) {
 43             /* ignore */
 44         }
 45         return clone;
 46     }
 47 
 48     /**
 49      * Gets the Object mapped from the specified key, or <code>null</code>
 50      * if no such mapping has been made.
 51      */
 52     public E get(int key) {
 53         return get(key, null);
 54     }
 55 
 56     /**
 57      * Gets the Object mapped from the specified key, or the specified Object
 58      * if no such mapping has been made.
 59      */
 60     @SuppressWarnings("unchecked")
 61     public E get(int key, E valueIfKeyNotFound) {
 62         int i = ContainerHelpers.binarySearch(mKeys, mSize, key);
 63 
 64         if (i < 0 || mValues[i] == DELETED) {
 65             return valueIfKeyNotFound;
 66         } else {
 67             return (E) mValues[i];
 68         }
 69     }
 70 
 71     /**
 72      * Removes the mapping from the specified key, if there was any.
 73      */
 74     public void delete(int key) {
 75         int i = ContainerHelpers.binarySearch(mKeys, mSize, key);
 76 
 77         if (i >= 0) {
 78             if (mValues[i] != DELETED) {
 79                 mValues[i] = DELETED;
 80                 mGarbage = true;
 81             }
 82         }
 83     }
 84 
 85     /**
 86      * @hide
 87      * Removes the mapping from the specified key, if there was any, returning the old value.
 88      */
 89     public E removeReturnOld(int key) {
 90         int i = ContainerHelpers.binarySearch(mKeys, mSize, key);
 91 
 92         if (i >= 0) {
 93             if (mValues[i] != DELETED) {
 94                 final E old = (E) mValues[i];
 95                 mValues[i] = DELETED;
 96                 mGarbage = true;
 97                 return old;
 98             }
 99         }
100         return null;
101     }
102 
103     /**
104      * Alias for {@link #delete(int)}.
105      */
106     public void remove(int key) {
107         delete(key);
108     }
109 
110     /**
111      * Removes the mapping at the specified index.
112      */
113     public void removeAt(int index) {
114         if (mValues[index] != DELETED) {
115             mValues[index] = DELETED;
116             mGarbage = true;
117         }
118     }
119 
120     /**
121      * Remove a range of mappings as a batch.
122      *
123      * @param index Index to begin at
124      * @param size Number of mappings to remove
125      */
126     public void removeAtRange(int index, int size) {
127         final int end = Math.min(mSize, index + size);
128         for (int i = index; i < end; i++) {
129             removeAt(i);
130         }
131     }
132 
133     private void gc() {
134         // Log.e("SparseArray", "gc start with " + mSize);
135 
136         int n = mSize;
137         int o = 0;
138         int[] keys = mKeys;
139         Object[] values = mValues;
140 
141         for (int i = 0; i < n; i++) {
142             Object val = values[i];
143 
144             if (val != DELETED) {
145                 if (i != o) {
146                     keys[o] = keys[i];
147                     values[o] = val;
148                     values[i] = null;
149                 }
150 
151                 o++;
152             }
153         }
154 
155         mGarbage = false;
156         mSize = o;
157 
158         // Log.e("SparseArray", "gc end with " + mSize);
159     }
160 
161     /**
162      * Adds a mapping from the specified key to the specified value,
163      * replacing the previous mapping from the specified key if there
164      * was one.
165      */
166     public void put(int key, E value) {
167         int i = ContainerHelpers.binarySearch(mKeys, mSize, key);
168 
169         if (i >= 0) {
170             mValues[i] = value;
171         } else {
172             i = ~i;
173 
174             if (i < mSize && mValues[i] == DELETED) {
175                 mKeys[i] = key;
176                 mValues[i] = value;
177                 return;
178             }
179 
180             if (mGarbage && mSize >= mKeys.length) {
181                 gc();
182 
183                 // Search again because indices may have changed.
184                 i = ~ContainerHelpers.binarySearch(mKeys, mSize, key);
185             }
186 
187             mKeys = GrowingArrayUtils.insert(mKeys, mSize, i, key);
188             mValues = GrowingArrayUtils.insert(mValues, mSize, i, value);
189             mSize++;
190         }
191     }
192 
193     /**
194      * Returns the number of key-value mappings that this SparseArray
195      * currently stores.
196      */
197     public int size() {
198         if (mGarbage) {
199             gc();
200         }
201 
202         return mSize;
203     }
204 
205     /**
206      * Given an index in the range <code>0...size()-1</code>, returns
207      * the key from the <code>index</code>th key-value mapping that this
208      * SparseArray stores.
209      *
210      * <p>The keys corresponding to indices in ascending order are guaranteed to
211      * be in ascending order, e.g., <code>keyAt(0)</code> will return the
212      * smallest key and <code>keyAt(size()-1)</code> will return the largest
213      * key.</p>
214      */
215     public int keyAt(int index) {
216         if (mGarbage) {
217             gc();
218         }
219 
220         return mKeys[index];
221     }
222 
223     /**
224      * Given an index in the range <code>0...size()-1</code>, returns
225      * the value from the <code>index</code>th key-value mapping that this
226      * SparseArray stores.
227      *
228      * <p>The values corresponding to indices in ascending order are guaranteed
229      * to be associated with keys in ascending order, e.g.,
230      * <code>valueAt(0)</code> will return the value associated with the
231      * smallest key and <code>valueAt(size()-1)</code> will return the value
232      * associated with the largest key.</p>
233      */
234     @SuppressWarnings("unchecked")
235     public E valueAt(int index) {
236         if (mGarbage) {
237             gc();
238         }
239 
240         return (E) mValues[index];
241     }
242 
243     /**
244      * Given an index in the range <code>0...size()-1</code>, sets a new
245      * value for the <code>index</code>th key-value mapping that this
246      * SparseArray stores.
247      */
248     public void setValueAt(int index, E value) {
249         if (mGarbage) {
250             gc();
251         }
252 
253         mValues[index] = value;
254     }
255 
256     /**
257      * Returns the index for which {@link #keyAt} would return the
258      * specified key, or a negative number if the specified
259      * key is not mapped.
260      */
261     public int indexOfKey(int key) {
262         if (mGarbage) {
263             gc();
264         }
265 
266         return ContainerHelpers.binarySearch(mKeys, mSize, key);
267     }
268 
269     /**
270      * Returns an index for which {@link #valueAt} would return the
271      * specified key, or a negative number if no keys map to the
272      * specified value.
273      * <p>Beware that this is a linear search, unlike lookups by key,
274      * and that multiple keys can map to the same value and this will
275      * find only one of them.
276      * <p>Note also that unlike most collections' {@code indexOf} methods,
277      * this method compares values using {@code ==} rather than {@code equals}.
278      */
279     public int indexOfValue(E value) {
280         if (mGarbage) {
281             gc();
282         }
283 
284         for (int i = 0; i < mSize; i++)
285             if (mValues[i] == value)
286                 return i;
287 
288         return -1;
289     }
290 
291     /**
292      * Removes all key-value mappings from this SparseArray.
293      */
294     public void clear() {
295         int n = mSize;
296         Object[] values = mValues;
297 
298         for (int i = 0; i < n; i++) {
299             values[i] = null;
300         }
301 
302         mSize = 0;
303         mGarbage = false;
304     }
305 
306     /**
307      * Puts a key/value pair into the array, optimizing for the case where
308      * the key is greater than all existing keys in the array.
309      */
310     public void append(int key, E value) {
311         if (mSize != 0 && key <= mKeys[mSize - 1]) {
312             put(key, value);
313             return;
314         }
315 
316         if (mGarbage && mSize >= mKeys.length) {
317             gc();
318         }
319 
320         mKeys = GrowingArrayUtils.append(mKeys, mSize, key);
321         mValues = GrowingArrayUtils.append(mValues, mSize, value);
322         mSize++;
323     }
324 
325     /**
326      * {@inheritDoc}
327      *
328      * <p>This implementation composes a string by iterating over its mappings. If
329      * this map contains itself as a value, the string "(this Map)"
330      * will appear in its place.
331      */
332     @Override
333     public String toString() {
334         if (size() <= 0) {
335             return "{}";
336         }
337 
338         StringBuilder buffer = new StringBuilder(mSize * 28);
339         buffer.append('{');
340         for (int i=0; i<mSize; i++) {
341             if (i > 0) {
342                 buffer.append(", ");
343             }
344             int key = keyAt(i);
345             buffer.append(key);
346             buffer.append('=');
347             Object value = valueAt(i);
348             if (value != this) {
349                 buffer.append(value);
350             } else {
351                 buffer.append("(this Map)");
352             }
353         }
354         buffer.append('}');
355         return buffer.toString();
356     }
357 }

 

 

##  ArrayMap

* 与 SparseArray 类似

posted @ 2017-03-08 15:43  熠然  阅读(1510)  评论(0编辑  收藏  举报