## 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 类似
直面挑战,躬身入局