## 简介
SparseArray,Android推荐我们使用它用来替代**HashMap** ,这样更加节省内存空间的使用。
SparseArray内部由两个数组组成,一个是int\[\]类型的mKeys,用来存放所有的键;另一个是Object\[\]类型的mValues,用来存放所有的值。
![](https://img.kancloud.cn/0e/cd/0ecd21489fb775c7ce47642b4a3774c3_580x200.png)
最常见的是拿SparseArray跟HashMap来做对比,由于SparseArray内部组成是两个数组,所以占用内存比HashMap要小。我们都知道,增删改查等操作都首先需要找到相应的键值对,而SparseArray**内部是通过二分查找来寻址**的,效率很明显要低于HashMap的常数级别的时间复杂度。提到二分查找,这里还需要提一下的是二分查找的前提是数组已经是排好序的,没错,SparseArray中就是**按照key进行升序排列的**。
综合起来来说,SparseArray所占空间优于HashMap,而效率低于HashMap,是典型的时间换空间,适合较小容量的存储
## 核心成员变量
~~~
//保存key的数组
private int[] mKeys;
//保存value的数组
private Object[] mValues
//大小
private int mSize;
~~~
## 构造函数
~~~
public SparseArray() {
this(10);
}
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;
}
~~~
构造函数做就是根据initialCapacity初始化mValues和mKeys
## put
~~~
public void put(int key, E value) {
//使用二分查找在key的位置
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;
}
//mGarbage大概意思是是否存在被删除的元素(垃圾)
//mSize >= mKeys.length 表示满了
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++;
}
}
///其实是把被删除的元素删除,其他元素向上挤,争取腾出位置
private void gc() {
int n = mSize;
int o = 0;
int[] keys = mKeys;
Object[] values = mValues;
for (int i = 0; i < n; i++) {
Object val = values[i];
if (val != DELETED) {
if (i != o) {
keys[o] = keys[i];
values[o] = val;
values[i] = null;
}
o++;
}
}
mGarbage = false;
mSize = o;
}
~~~
## get
~~~
public E get(int key, E valueIfKeyNotFound) {
int i = ContainerHelpers.binarySearch(mKeys, mSize, key);
if (i < 0 || mValues[i] == DELETED) {
return valueIfKeyNotFound;
} else {
return (E) mValues[i];
}
~~~
get的亮点不多,就是一个二分查找找到index,然后返回value
## remove
~~~
public void delete(int key) {
int i = ContainerHelpers.binarySearch(mKeys, mSize, key);
if (i >= 0) {
if (mValues[i] != DELETED) {
mValues[i] = DELETED;
mGarbage = true;
}
}
}
~~~
- Java
- Object
- 内部类
- 异常
- 注解
- 反射
- 静态代理与动态代理
- 泛型
- 继承
- JVM
- ClassLoader
- String
- 数据结构
- Java集合类
- ArrayList
- LinkedList
- HashSet
- TreeSet
- HashMap
- TreeMap
- HashTable
- 并发集合类
- Collections
- CopyOnWriteArrayList
- ConcurrentHashMap
- Android集合类
- SparseArray
- ArrayMap
- 算法
- 排序
- 常用算法
- LeetCode
- 二叉树遍历
- 剑指
- 数据结构、算法和数据操作
- 高质量的代码
- 解决问题的思路
- 优化时间和空间效率
- 面试中的各项能力
- 算法心得
- 并发
- Thread
- 锁
- java内存模型
- CAS
- 原子类Atomic
- volatile
- synchronized
- Object.wait-notify
- Lock
- Lock之AQS
- Lock子类
- 锁小结
- 堵塞队列
- 生产者消费者模型
- 线程池