Android-SparseArray

前言

Linus Benedict Torvalds : RTFSC – Read The Funning Source Code

概述

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.
翻译:SparseArrays 将 integers 映射到 Objects。与正常的数组不同,它允许在数组中有间隙。它的目的是比一般使用 HashMap 对内存的使用更加优化。因为它每个键值对避免了自动拆包键值和它的数据结构不依赖额外的条目封装。

SparseArray的数据结构使用的是稀疏数组(Sparse * array),所谓稀疏数组就是数组中大部分的内容值都未被使用(或都为零),在数组中仅有少部分的空间使用。因此造成内存空间的浪费,为了节省内存空间,并且不影响数组中原有的内容值,于是可以采用一种压缩的方式来表示稀疏数组的内容。

使用

1
2
3
4
5
6
7
8
9
SparseArray<String>sparse = new SparseArray<String>();
for(int i = 0; i<MAX; ++i) {
// 增加
sparse.put(i, String.valueOf(i));
sparse.append(i, " " + String.valueOf(i));
// 修改
array.setValueAt(i, String.valueOf(i));
}

初始化

1
SparseArray<View> array = new SparseArray<View>();

增加数据

1
2
3
4
// public void put(int key, E value) {}
array.put(KEY, btn);
// public void append(int key, E value){}
array.append(KEY, btn);

修改数据

1
2
3
4
5
// 在put数据之前,会先查找要put的数据是否已经存在,如果存在就是修改,不存在就添加。
// public void put(int key, E value)
array.put(KEY, btn);
// public void setValueAt(int index, E value)
array.setValueAt(KEY, btn02);

查找数据

1
2
3
4
5
// public E get(int key)
array.get(KEY);
// public E get(int key, E valueIfKeyNotFound)
// 其中get(int key)也只是调用了 get(int key,E valueIfKeyNotFound),最后一个从传参的变量名就能看出,传入的是找不到的时候返回的值.get(int key)当找不到的时候,默认返回null。
array.get(KEY, btn); // 如果这个key找不到value,那么就返回第二个参数。和default value一样

通过位置,查找键的值

1
2
3
// 查看第几个位置的键:
// public int keyAt(int index)
array.keyAt(1); // 如果找不到就返回-1

通过位置,查找值

1
2
3
4
5
6
// 查看第几个位置的值:
// public E valueAt(int index)
array.valueAt(1);
// 查看值所在位置,没有的话返回-1:
// public int indexOfValue(E value)
array.indexOfValue(btn);

特性

优点

  1. 在存储量不大的情况下,SparseArray 在可以用来替换 HashMap>。在此情况下,SparseArray的内存消耗始终小于HashMap。

缺点

  1. 有一定的性能上的消耗的,并不适合当成包含大量元素的容器。
  2. 不是线程安全的。
  3. 插入数据按 key 大小顺序插入,使用对 key 进行二分查找。查找效率上不如 HashMap。
  4. 对删除做了一个优化,不会直接立即删除一个元素,而是把该位置的值设置成 DELETED,尝试 reuse。

延伸

前提都是在结构体量不是特别大的情况下

1
2
3
4
5
6
7
8
9
10
11
// HashMap<Integer, E>
HashMap<Integer, E> hashMap = new HashMap<Integer, E>();
替换为:SparseArray<E> sparseArray = new SparseArray<E>();
// HashMap<Integer, Boolean>
HashMap<Integer, Boolean> hashMap = new HashMap<Integer, Boolean>
替换为:SparseBooleanArray array = new SparseBooleanArray();
// HashMap<Integer, Integer>
HashMap<Integer, Integer> hashMap = new HashMap<Integer, Integer>
替换为:SparseIntArray array = new SparseIntArray();