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. SQLSERVER一些公用DLL的作用解释

    如果你的SQLSERVER安装在C盘的话,下面的路径就是相应SQLSERVER版本的公用DLL的存放路径 SQL2005 C:\Program Files\Microsoft SQL Server\9 ...

  2. mysql嵌套查询

    select * from(select t.`name` `name`,count(*) count from company t group by t.`name`) aa where aa.co ...

  3. C++编程注意事项

    1.所有成员变量在构造函数中进行初始化操作,如指针赋值为空,bool赋值为FALSE(默认为TRUE); 2.构造函数与析构函数配对出现,执行反向操作,保证执行析构之后,没有遗留问题存在: 3.如果需 ...

  4. 一个fibonacci数列简单求和的问题

    前段时间老师在讲函数调用的时候,用Fibonacci数列来演示了一下,因为以前没怎么接触过Fibonacci,所以当时很懵. 当时让求的是Fibonacci数列中,第N位值为多少,当时老师写的是: 之 ...

  5. java新手笔记22 接口示例2

    1.USB package com.yfs.javase; public interface USB { //定义规范 public void read(); public void write(); ...

  6. switch case实现两个数的算术运算

    方法一: package com.liaojianya.chapter1; import java.util.Scanner; public class SwitchDemo1 { public st ...

  7. Python GUI with Tkinter (from youtube) 在youtube上能找到很多编程视频...

    Python GUI with Tkinter - 1 - Introduction以上链接是一个python tkinter视频系列的第一讲的链接.虽然英语不好,但是,程序还是看得懂的(照着做就可以 ...

  8. 2、Charm Bracelet( poj 3624)简单0-1背包

    题意:有n件手镯,总重量不能超过M,每个手镯有一个体重W[i]和魅力V[i],问在不超过M的情况下能获得的魅力总和 思路:把M当背包总容量,用0-1背包写 代码: #include <iostr ...

  9. UIView-图层方法

    // // ViewController.m // UIView-图层概念 // // Created by wangtouwang on 15/5/5. // Copyright (c) 2015年 ...

  10. BZOJ 1052: [HAOI2007]覆盖问题

    BZOJ 1052: [HAOI2007]覆盖问题 题意:给定平面上横纵坐标在-1e9~1e9内的20000个整数点的坐标,用三个大小相同边平行于坐标轴的正方形覆盖(在边界上的也算),问正方形的边长最 ...