性能优化:使用SparseArray代替HashMap<Integer,Object>(转)
HashMap是java里比较常用的一个集合类,我比较习惯用来缓存一些处理后的结果。最近在做一个Android项目,在代码中定义这样一个变量,实例化时,Eclipse却给出了一个 performance 警告。

意思就是说用SparseArray<E>来替代,以获取更好性能。老实说,对SparseArray并不熟悉,第一感觉应该是Android提供的一个类。按住Ctrl点击进入SparseArray的源码,果不其然,确定是Android提供的一个工具类。

单纯从字面上来理解,SparseArray指的是稀疏数组(Sparse array),所谓稀疏数组就是数组中大部分的内容值都未被使用(或都为零),在数组中仅有少部分的空间使用。因此造成内存空间的浪费,为了节省内存空间,并且不影响数组中原有的内容值,我们可以采用一种压缩的方式来表示稀疏数组的内容。
假设有一个9*7的数组,其内容如下:

在此数组中,共有63个空间,但却只使用了5个元素,造成58个元素空间的浪费。以下我们就使用稀疏数组重新来定义这个数组:

其中在稀疏数组中第一部分所记录的是原数组的列数和行数以及元素使用的个数、第二部分所记录的是原数组中元素的位置和内容。经过压缩之后,原来需要声明大小为63的数组,而使用压缩后,只需要声明大小为6*3的数组,仅需18个存储空间。
继续阅读SparseArray的源码,从构造方法我们可以看出,它和一般的List一样,可以预先设置容器大小,默认的大小是10:
- public SparseArray() {
- this(10);
- }
- public SparseArray(int initialCapacity) {
- initialCapacity = ArrayUtils.idealIntArraySize(initialCapacity);
- mKeys = new int[initialCapacity];
- mValues = new Object[initialCapacity];
- mSize = 0;
- }
它有两个方法可以添加键值对:
- public void put(int key, E value) {}
- public void append(int key, E value){}
- public void delete(int key) {}
- public void remove(int key) {} //直接调用的delete(int key)
- public void removeAt(int index){}
- public void clear(){}
- 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);
- }
- …………
- public void put(int key, E value)
- public void setValueAt(int index, E value)
- public E get(int key)
- public E get(int key, E valueIfKeyNotFound)
查看第几个位置的键:
- public int keyAt(int index)
查看第几个位置的值:
- public E valueAt(int index)
1 |
public int indexOfValue(E value) |
最后,发现其核心就是折半查找函数(binarySearch),算法设计的很不错。
1 |
private static int binarySearch(int[] a,int start, int len, intkey) { |
2 |
inthigh = start + len, low = start - 1, guess; |
3 |
4 |
while(high - low > 1) { |
5 |
guess = (high + low) /2; |
6 |
7 |
if(a[guess] < key) |
8 |
low = guess; |
9 |
else |
10 |
high = guess; |
11 |
} |
12 |
13 |
if(high == start + len) |
14 |
return~(start + len); |
15 |
elseif (a[high] == key) |
16 |
returnhigh; |
17 |
else |
18 |
return~high; |
19 |
} |
相应的也有SparseBooleanArray,用来取代HashMap<Integer, Boolean>,SparseIntArray用来取代HashMap<Integer, Integer>,大家有兴趣的可以研究。
总结:SparseArray是android里为<Interger,Object>这样的Hashmap而专门写的类,目的是提高效率,其核心是折半查找函数(binarySearch)。在Android中,当我们需要定义
1 |
HashMap<Integer, E> hashMap = new HashMap<Integer, E>(); |
时,我们可以使用如下的方式来取得更好的性能。
1 |
SparseArray<E> sparseArray = new SparseArray<E>(); |
性能优化:使用SparseArray代替HashMap<Integer,Object>(转)的更多相关文章
- Android 开发性能优化之SparseArray(三)
SparseArray是android里为<Interger,Object>这样的Hashmap而专门写的class,目的是提高效率,其核心是折半查找函数(binarySearch) pr ...
- Android 开发性能优化之SparseArray(一)
多数Android开发者都知道在Android中可以使用HashMap来映射一种对应关系,在java开发中HashMap也算是一种很重要的数据存储结构.然后很多人在Android开发中多数都会用Has ...
- Android 开发性能优化之SparseArray(二)
一.SparseIntArray API SparseIntArrays map integers to integers. Unlike a normal array of integers, t ...
- 关于Android中ArrayMap/SparseArray比HashMap性能好的深入研究
由于网上有朋友对于这个问题已经有了很详细的研究,所以我就不班门弄斧了: 转载于:http://android-performance.com/android/2014/02/10/android-sp ...
- Android应用性能优化之使用SparseArray替代HashMap
HashMap是java里比较常用的一个集合类,我比较习惯用来缓存一些处理后的结果.最近在做一个Android项目,在代码中定义这样一个变量,实例化时,Eclipse却给出了一个 performanc ...
- Android 性能优化 SparseArray【转载】
原文地址:Android学习笔记之性能优化SparseArray 学习内容: 1.Android中SparseArray的使用.. 昨天研究完横向二级菜单,发现其中使用了SparseArray去替 ...
- Android学习笔记之性能优化SparseArray
PS:终于考完试了.来一发.微机原理充满了危机.不过好在数据库89分,还是非常欣慰的. 学习内容: 1.Android中SparseArray的使用.. 昨天研究完横向二级菜单,发现其中使用了Sp ...
- android:应用性能优化SparseArray
HashMap是java里比较常用的一个集合类,我比较习惯用来缓存一些处理后的结果.最近在做一个Android项目,在代码中定义这样一个变量,实例化时,Eclipse却给出了一个 performanc ...
- SparseArray替代HashMap来提高性能
SparseArray是 Android框架独有的类,在标准的JDK中不存在这个类.它要比 HashMap 节省内存,某些情况下比HashMap性能更好,按照官方问答的解释,主要是因为SparseAr ...
随机推荐
- Linux学习7-文件操作
标准I/O库(stdio)及其头文件stdio.h 为底层I/O系统调用提供了一个通用的接口. 在标准I/O库中,与底层文件描述符对应的是流(stream),它被实现为指向结构FILE的指针. 在启动 ...
- [HNOI2013]比赛 (用Hash实现记忆化搜索)
[HNOI2013]比赛 题目描述 沫沫非常喜欢看足球赛,但因为沉迷于射箭游戏,错过了最近的一次足球联赛.此次联 赛共N支球队参加,比赛规则如下: (1) 每两支球队之间踢一场比赛. (2) 若平局, ...
- Wireshark按照域名过滤
HTTP协议 http.host == "http://baidu.net" DNS协议 dns.qry.name=="www.baidu.com"
- Linux网络状态工具ss命令使用详解【转】
ss命令用于显示socket状态. 他可以显示PACKET sockets, TCP sockets, UDP sockets, DCCP sockets, RAW sockets, Unix dom ...
- 【译】EntityFramework6与EntityFrameworkCore的区别
EntityFramework6 EF6 是一个久经考验的数据库访问技术,发展多年,拥有许多特性,并且成熟稳定.2008年EF作为 .Net 3.5 Sp1 和Visual Studio 2008 S ...
- Axure RP 快速原型设计工具
Axure RP是美国Axure Software Solution公司旗舰产品,是一个专业的快速原型设计工具,让负责定义需求和规格.设计功能和界面的专家能够快速创建应用软件或Web网站的线框图 ...
- redis,nodejs,php,pub/sub 实战: 微信语音识别
2015年5月22日 20:20:20 星期五 效果: 这边对微信说话, 浏览器端及时显示语音识别的文字 注意: 在连接socket.io时, 按下浏览器f12, 如果一直有请求不断的刷, 说明so ...
- jquery实现模拟select下拉框效果
<IGNORE_JS_OP style="WORD-WRAP: break-word"> <!DOCTYPE html PUBLIC "-//W3C// ...
- Coursera台大机器学习技法课程笔记14-Radial Basis Function Network
将Radial Basis Function与Network相结合.实际上衡量两个点的相似性:距离越近,值越大. 将神经元换为与距离有关的函数,就是RBF Network: 可以用kernel和RBF ...
- Delphi中使用ActiveX的一些心得
使用方法分为两种:一.直接把可视化的ActiveX控件放到程序中:二.运行时根据需要实时建立. 如果是直接使用,则应用程序在初始化的过程中会自动寻找.创建所需的ActiveX控件,如果控件没有注册, ...