使用SparseArray代替HashMap
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:
|
1
2
3
4
5
6
7
8
9
10
11
|
public SparseArray(){
this(10);
}
public SparseArray(intinitialCapacity){
initialCapacity=ArrayUtils.idealIntArraySize(initialCapacity);
mKeys=new int[initialCapacity];
mValues=new Object[initialCapacity];
mSize=0;
}
|
再来看看它对数据的“增删改查”。
它有两个方法可以添加键值对:
|
1
2
|
public voidput(intkey,Evalue){}
public voidappend(intkey,Evalue){}
|
有四个方法可以执行删除操作:
|
1
2
3
4
|
public voiddelete(intkey){}
public voidremove(intkey){}//直接调用的delete(int key)
public voidremoveAt(intindex){}
public voidclear(){}
|
修改数据起初以为只有setValueAt(int index, E value)可以修改数据,但后来发现put(int key, E value)也可以修改数据,我们查看put(int key, E value)的源码可知,在put数据之前,会先查找要put的数据是否已经存在,如果存在就是修改,不存在就添加。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
public voidput(intkey,Evalue){
inti=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);
}
…………
|
所以,修改数据实际也有两种方法:
|
1
2
|
public voidput(intkey,Evalue)
public voidsetValueAt(intindex,Evalue)
|
最后再来看看如何查找数据。有两个方法可以查询取值:
|
1
2
|
publicEget(intkey)
publicEget(intkey,EvalueIfKeyNotFound)
|
其中get(int key)也只是调用了 get(int key,E valueIfKeyNotFound),最后一个从传参的变量名就能看出,传入的是找不到的时候返回的值.get(int key)当找不到的时候,默认返回null。
查看第几个位置的键:
|
1
|
public intkeyAt(intindex)
|
有一点需要注意的是,查看键所在位置,由于是采用二分法查找键的位置,所以找不到时返回小于0的数值,而不是返回-1。返回的负值是表示它在找不到时所在的位置。
查看第几个位置的值:
|
1
|
publicEvalueAt(intindex)
|
查看值所在位置,没有的话返回-1:
|
1
|
public intindexOfValue(Evalue)
|
最后,发现其核心就是折半查找函数(binarySearch),算法设计的很不错。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
private staticintbinarySearch(int[] a,intstart,intlen,intkey){
inthigh=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);
elseif(a[high]==key)
returnhigh;
else
return~high;
}
|
相应的也有SparseBooleanArray,用来取代HashMap<Integer, Boolean>,SparseIntArray用来取代HashMap<Integer, Integer>,大家有兴趣的可以研究。
总结:SparseArray是android里为<Interger,Object>这样的Hashmap而专门写的类,目的是提高效率,其核心是折半查找函数(binarySearch)。在Android中,当我们需要定义
|
1
|
HashMap<Integer,E>hashMap=newHashMap<Integer,E>();
|
时,我们可以使用如下的方式来取得更好的性能.
|
1
|
SparseArray<E>sparseArray=newSparseArray<E>();
|
原文链接:http://liuzhichao.com/p/832.html
使用SparseArray代替HashMap的更多相关文章
- 关于Android中ArrayMap/SparseArray比HashMap性能好的深入研究
由于网上有朋友对于这个问题已经有了很详细的研究,所以我就不班门弄斧了: 转载于:http://android-performance.com/android/2014/02/10/android-sp ...
- SparseArray代替HashMap
相信大家都明白,手机软件的开发不同于PC软件的开发,因为手机性能相对有限,内存也有限,所谓“寸土寸金”,可能稍有不慎,就会导致性能的明显降低.Android为了方便开发者,特意在android.uti ...
- SparseArray替代HashMap来提高性能
SparseArray是 Android框架独有的类,在标准的JDK中不存在这个类.它要比 HashMap 节省内存,某些情况下比HashMap性能更好,按照官方问答的解释,主要是因为SparseAr ...
- Android开发 使用SparseArray代替HashMap[转载]
源作者:Android小Y链接:https://www.jianshu.com/p/1828f14d7955来源:简书 前言 Android开发中,一个好的应用,除了要有吸引人的功能和交互之外,在性能 ...
- 73.Android之SparseArray替代HashMap
转载:https://liuzhichao.com/p/832.html HashMap是java里比较常用的一个集合类,我比较习惯用来缓存一些处理后的结果.最近在做一个Android项目,在代码中定 ...
- Android应用性能优化之使用SparseArray替代HashMap
HashMap是java里比较常用的一个集合类,我比较习惯用来缓存一些处理后的结果.最近在做一个Android项目,在代码中定义这样一个变量,实例化时,Eclipse却给出了一个 performanc ...
- 【移动开发】SparseArray替代HashMap
SparseArray是android里为<Interger,Object>这样的Hashmap而专门写的class,目的是提高效率,其核心是折半查找函数(binarySearch). p ...
- 性能优化:使用SparseArray代替HashMap<Integer,Object>(转)
HashMap是java里比较常用的一个集合类,我比较习惯用来缓存一些处理后的结果.最近在做一个Android项目,在代码中定义这样一个变量,实例化时,Eclipse却给出了一个 performanc ...
- 用SparseArray代替HashMap
SparseArray是android提供的一个工具类,它可以用来替代hashmap进行对象的存储,其内部实现了一个矩阵压缩算法,很适合存储稀疏矩阵的. PS:support包中还提供了兼容的类Spa ...
随机推荐
- Unity3D 之2D动画机
这里来讲解一下2D动画机的使用 2D的时候,默认的情况下,可以调用默认的站立之类的动画,然后通过触发,可以变化自己的动画. 一:将一个图切成一些一个元素 二:创建一个精灵,给精灵添加一个动画机 三:给 ...
- Linux操作系统搭建JDK开发环境
在Linuxer系统中,jdk环境常常是必需的,下面介绍下Oracle官方JDK安装方式 第一步:去jdk官网下载对应版本的JDK安装文件 第二步:解压文件,修改文件名 $ sudo mkdir /u ...
- Linux操作系统安装Nvidia显卡驱动
一直以来,Linux分支系统使用过程中都有驱动适配麻烦,完全适配的驱动也不多.对于Nvidia显卡而言,一般Linux各分支操作系统虽然提供了N卡开源驱动工程Nouveau,但是性能上还是有待提高.下 ...
- 在 APK 中找不到对应的 securityguard***.so 文件或者 so 文件载入出错
1.解压查看你的apk是不是将so打进去了,如果没有打进入查看自己的jnilibs是否指定 2.查看手机是否是64的手机.因为百川的安全包没有64的支持,所以目前是以兼容包的形式给的包.如果第三方有6 ...
- 最简单的基于Flash的流媒体示例:网页播放器(HTTP,RTMP,HLS)
http://blog.csdn.net/leixiaohua1020/article/details/43936415 ======================================= ...
- 页面嵌套 Iframe 产生缓存导致页面数据不刷新问题
最近遇到个比较古怪的问题:当页面嵌套多个 Iframe 时会出现 Iframe 里包含的页面无法看到最新的页面信息. 初步解决方案,在 Iframe 指向的页面地址后缀添加一个随机数或者时间戳.这样能 ...
- 经历:sybase的sql查询,当传递的参数中包含全角空格(\u00a0),查询慢
今天,我遇到了一个sybase数据库查询的问题.一句简单的sql,但是不知道为什么查询不出来,导致生产生产服务器频频挂掉.吓得我的小心脏砰砰啊. select DISTINCT A.FCIL_CDE ...
- shell通过ftp实现上传/下载文件
直接代码,shell文件名为testFtptool.sh: #!/bin/bash ########################################################## ...
- Qt标准对话框之QColorDialog
Qt中提供了一些标准的对话框,用于实现一些常用的预定义功能,比如本节中将要介绍的颜色对话框——QColorDialog. 在不同的系统平台下,颜色对话框的显示效果可能会有所不同,主要因系统主题风格而异 ...
- 技术贴:asp.net实现唯一账户在线 禁止同一帐号同时在线 asp.net实现您的帐号在别处登录,您已被迫下线!
技术要点: Application 全局变量的使用 hashtable 的使用 Session 对应唯一sessionID 标志会话状态 webpage 继承 BasePage的技术 整体比较简单,主 ...