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&gt;=0){
            mValues[i]=value;
        }else{
            i=~i;
 
            if(i&lt;mSize&amp;&amp;mValues[i]==DELETED){
                mKeys[i]=key;
                mValues[i]=value;
                return;
            }
 
            if(mGarbage&amp;&amp;mSize&gt;=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&gt;1){
            guess=(high+low)/2;
 
            if(a[guess]&lt;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的更多相关文章

  1. 关于Android中ArrayMap/SparseArray比HashMap性能好的深入研究

    由于网上有朋友对于这个问题已经有了很详细的研究,所以我就不班门弄斧了: 转载于:http://android-performance.com/android/2014/02/10/android-sp ...

  2. SparseArray代替HashMap

    相信大家都明白,手机软件的开发不同于PC软件的开发,因为手机性能相对有限,内存也有限,所谓“寸土寸金”,可能稍有不慎,就会导致性能的明显降低.Android为了方便开发者,特意在android.uti ...

  3. SparseArray替代HashMap来提高性能

    SparseArray是 Android框架独有的类,在标准的JDK中不存在这个类.它要比 HashMap 节省内存,某些情况下比HashMap性能更好,按照官方问答的解释,主要是因为SparseAr ...

  4. Android开发 使用SparseArray代替HashMap[转载]

    源作者:Android小Y链接:https://www.jianshu.com/p/1828f14d7955来源:简书 前言 Android开发中,一个好的应用,除了要有吸引人的功能和交互之外,在性能 ...

  5. 73.Android之SparseArray替代HashMap

    转载:https://liuzhichao.com/p/832.html HashMap是java里比较常用的一个集合类,我比较习惯用来缓存一些处理后的结果.最近在做一个Android项目,在代码中定 ...

  6. Android应用性能优化之使用SparseArray替代HashMap

    HashMap是java里比较常用的一个集合类,我比较习惯用来缓存一些处理后的结果.最近在做一个Android项目,在代码中定义这样一个变量,实例化时,Eclipse却给出了一个 performanc ...

  7. 【移动开发】SparseArray替代HashMap

    SparseArray是android里为<Interger,Object>这样的Hashmap而专门写的class,目的是提高效率,其核心是折半查找函数(binarySearch). p ...

  8. 性能优化:使用SparseArray代替HashMap<Integer,Object>(转)

    HashMap是java里比较常用的一个集合类,我比较习惯用来缓存一些处理后的结果.最近在做一个Android项目,在代码中定义这样一个变量,实例化时,Eclipse却给出了一个 performanc ...

  9. 用SparseArray代替HashMap

    SparseArray是android提供的一个工具类,它可以用来替代hashmap进行对象的存储,其内部实现了一个矩阵压缩算法,很适合存储稀疏矩阵的. PS:support包中还提供了兼容的类Spa ...

随机推荐

  1. html 微信开发——微信授权

    微信JS-SDK说明文档 链接地址:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html 微信web开发:http: ...

  2. MVC小系列(十二)【RenderAction和RenderPartial区别】

    二者作用:RenderAction:渲染分部视图到页面上,要求提供Action和控制器名称RenderPartial:渲染分部视图到页面上,要求提供分部视图的名称,即路径,如果是在当前控制下或者sha ...

  3. SQL Server调优系列基础篇 - 并行运算总结(二)

    前言 上一篇文章我们介绍了查看查询计划的并行运行方式. 本篇我们接着分析SQL Server的并行运算. 闲言少叙,直接进入本篇的正题. 技术准备 同前几篇一样,基于SQL Server2008R2版 ...

  4. WEB开发时Browser控件得到C:\fakepath\ 的解决方式

    IE9中JS获得文件上传控件的路径不对,为:C:\fakepath\ 原来要修改:  工具 -> Internet选项 -> 安全 -> 自定义级别 -> 将本地文件上载至服务 ...

  5. NET异步调用Webserver

    之前,有个同事跑来问我一堆的什么多线程异步进行调用Sap的服务再突然把进程关闭,还说要设置一个循环判断调用的结果,搞得我听的一头雾水,但是我明显感觉到他的设计思路已经渐行渐远了...已经再偏远的山区中 ...

  6. [001] winnie the pooh - 读后记

    winnie the pooh 我是在伍君仪透析英语视频培训班,获得这本书的,PDF格式的(排版不是很好,和当当上的相比有部分章节缺失) 这是我第一本采用透析法读完的英文书. 今天(2015年10月2 ...

  7. 13_输出映射1_resultType

    输出映射主要有两种:resultType和resultMap [resultType] 可以返回三种类型 pojo对象:例如select * from user where id=? pojo对象列表 ...

  8. java.util.HashMap源码分析

    在java jdk8中对HashMap的源码进行了优化,在jdk7中,HashMap处理“碰撞”的时候,都是采用链表来存储,当碰撞的结点很多时,查询时间是O(n). 在jdk8中,HashMap处理“ ...

  9. 用source code编译安装Xdebug

    1. Unpack the tarball: tar -xzf xdebug-2.2.x.tgz.  Note that you do not need to unpack the tarball i ...

  10. Chrome浏览器报错:Origin null is not allowed by Access-Control-Allow-Origin.

    问题:Chrome浏览器报错:Origin null is not allowed by Access-Control-Allow-Origin. 原因:.js文件中使用load()方法,而Chrom ...