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. 将Cell中的视图取出传递到根视图

    当我们点击Cell中的某个图片时,图片会有一种从Cell中取出,放大,然后再回到原来的Cell中的效果.我的想法是:当Cell中的图片用button 来显示.当我们点击Cell中的这个button的时 ...

  2. linux 列出安装包内的文件

    rpm系列: 1. 文件类型  rpm -qpl xxx.rpm2. 已安装文件  rpm -ql packagename debain系列: dpkg -c xxxx.deb

  3. Flexbox盒子弹性布局

    Can I Use? 2. 概念: 当你给一个元素使用了flexbox模块,那么它的子元素就会指定的方向在水平或者纵向方向排列.这些子元素会按照一定的比例进行扩展或收缩来填补容器的可用空间. < ...

  4. js使用正则表达式去空格

    写成类的方法格式如下:(str.trim();) <script language="javascript"> String.prototype.trim=functi ...

  5. SSM配置

    <?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.spr ...

  6. 享元模式(咖啡屋)【java与模式】

    package com.javapatterns.flyweight.coffeeshop; public class Flavor extends Order { private String fl ...

  7. HDU 1619 Unidirectional TSP(单向TSP + 路径打印)

    Unidirectional TSP Problem Description Problems that require minimum paths through some domain appea ...

  8. 操作系统之进程篇(4)--经典进程间通信(IPC)问题

    1. 哲学家进餐问题: 问题描述: 五个哲学家在一个圆桌上进餐,每人的面前放了一盘意大利面,两个盘子之间有一个叉子,但是由于盘子里面的面条十分光滑,需要两个叉子才能进行就餐行为.餐桌的布局如下图所示: ...

  9. 【BZOJ3884】【降幂大法】上帝与集合的正确用法

    Description 根据一些书上的记载,上帝的一次失败的创世经历是这样的: 第一天, 上帝创造了一个世界的基本元素,称做“元”. 第二天, 上帝创造了一个新的元素,称作“α”.“α”被定义为“元” ...

  10. ASP.NET中的母版页

    添加一个"母版页",使用<asp:ContentPlaceHolder>挖坑,新建的母版页已经自动设置了两个ContentPlaceHolder创建使用母版页的具体页面 ...