Android应用性能优化之使用SparseArray替代HashMap
来源:互联网 发布:天池大数据 经验 编辑:程序博客网 时间:2024/06/06 16:25
一、概述
最近在项目中看到了SparseArray,好奇研究了下。 SparseArray是Android框架独有的类,在标准的JDK中不存在这个类。它要比 HashMap 节省内存,某些情况下比HashMap性能更好,按照官方问答的解释,主要是因为SparseArray不需要对key和value进行auto-boxing(将原始类型封装为对象类型,比如把int类型封装成Integer类型),结构比HashMap简单(SparseArray内部主要使用两个一维数组来保存数据,一个用来存key,一个用来存value)不需要额外的额外的数据结构(主要是针对HashMap中的HashMapEntry而言的)。
二、详解
假设有一个9*7的数组,其内容如下:在此数组中,共有63个空间,但却只使用了5个元素,造成58个元素空间的浪费。以下我们就使用稀疏数组重新来定义这个数组:
其中在稀疏数组中第一部分所记录的是原数组的列数和行数以及元素使用的个数、第二部分所记录的是原数组中元素的位置和内容。经过压缩之后,原来需要声明大小为63的数组,而使用压缩后,只需要声明大小为6*3的数组,仅需18个存储空间。
光说不行啊,不能你说性能好就性能好,是骡子是马拉出来溜溜,我们写两段测试程序: 代码1:
代码2:int MAX = 100000;long start = System.currentTimeMillis();HashMap hash = new HashMap();for (int i = 0; i < MAX; i++) { hash.put(i, String.valueOf(i));}long ts = System.currentTimeMillis() - start;
上面两段代码中,我们分别用HashMap和SpaseArray正序插入100000条数据,数据如下:int MAX = 100000;long start = System.currentTimeMillis();SparseArray sparse = new SparseArray();for (int i = 0; i < MAX; i++) { sparse.put(i, String.valueOf(i));}long ts = System.currentTimeMillis() - start;
并且在正序条件下,时间上比HashMap快33%左右。
我们把正序变为反序试试 代码3:
代码4:int MAX = 100000;long start = System.currentTimeMillis();HashMap hash = new HashMap();for (int i = 0; i < MAX; i++) { hash.put(MAX - i -1, String.valueOf(i));}long ts = System.currentTimeMillis() - start;
int MAX = 100000;long start = System.currentTimeMillis();SparseArray sparse = new SparseArray();for (int i = 0; i < MAX; i++) { sparse.put(MAX - i -1, String.valueOf(i));}long ts = System.currentTimeMillis() - start;
运行结果如下:
通过结果我们看出,在正序插入数据时候,SparseArray比HashMap要快一些;
HashMap不管是倒序还是正序开销几乎是一样的;但是SparseArray的倒序插入要比正序插入要慢10倍以上,这时为什么呢?
跟进源码,找到put方法:
public void put(int key, E value) { int i = binarySearch(mKeys, 0, 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 = ~binarySearch(mKeys, 0, mSize, key); } …………
在put数据之前,会先查找要put的数据是否已经存在,如果存在就是修改,不存在就添加。其中有个查找的过程,就是binarySearch,这是个什么鬼啊,跟进去看看:
soga,原来是二分查找。那么原因也就找到了,正是因为SparseArray在检索数据的时候使用的是二分查找,所以每次插入新数据的时候SparseArray都需要重新排序,所以代码4中,逆序是最差情况。private static int binarySearch(int[] a, int start, int len, int key) { int high = start + len, low = start - 1, guess; while (high - low > 1) { guess = (high + low) / 2; if (a[guess] < key) low = guess; else high = guess; } if (high == start + len) return ~(start + len); else if (a[high] == key) return high; else return ~high; }
另外,当SparseArray中存在需要检索的下标时,SparseArray的性能略胜一筹。但是当检索的下标比较离散时,SparseArray需要使用多次二分检索,性能比hash检索方式要慢一些了,但是按照官方文档的说法性能差异不是很大,不超过50%( For containers holding up to hundreds of items, the performance difference is not significant, less than 50%.)
三、总结
总结:SparseArray是android里为这样的Hashmap而专门写的类,目的是提高效率,其核心是折半查找函数(binarySearch)。在Android中,当我们需要定义
HashMap hashMap = new HashMap();时,我们可以使用如下的方式来取得更好的性能.
SparseArray sparseArray = new SparseArray();
0 0
- Android应用性能优化之使用SparseArray替代HashMap
- Android应用性能优化之使用SparseArray替代HashMap
- Android应用性能优化之使用SparseArray替代HashMap
- Android应用性能优化之使用SparseArray替代HashMap
- Android应用性能优化之使用SparseArray替代HashMap
- Android应用性能优化之使用SparseArray替代HashMap
- Android应用性能优化之使用SparseArray替代HashMap
- Android应用性能优化之使用SparseArray替代HashMap
- Android应用性能优化之使用SparseArray替代HashMap
- Android应用性能优化之使用SparseArray替代HashMap
- Android应用性能优化之使用SparseArray替代HashMap
- Android应用性能优化之使用SparseArray替代HashMap
- Android应用性能优化之使用SparseArray替代HashMap
- Android应用性能优化之使用SparseArray替代HashMap
- Android应用性能优化之使用SparseArray替代HashMap
- Android应用性能优化之使用SparseArray替代HashMap
- Android应用性能优化之使用SparseArray替代HashMap
- Android应用性能优化之使用SparseArray替代HashMap
- 欢迎使用CSDN-markdown编辑器
- 物联网概述
- 参数嗅探(Parameter Sniffing)(2/2)
- 解决网站无法实现APK文件下载问题
- MySQL索引的创建、删除和查看
- Android应用性能优化之使用SparseArray替代HashMap
- CDH安装中的一些问题及解决方法
- 迫不及待的想在Ubuntu 16.04 安装 NVIDIA CUDA Toolkit 7.5并安装gromacs5.1.2看这里
- AngularJs依赖注入
- 对象序列化 ObjectInputStream ObjectOutputStream
- word/excel在android读取,写入,更新数据
- HBase架构核心模块
- 软件架构的风险消除策略
- 操作系统文件系统设计实验报告