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. public SparseArray() {
  2. this(10);
  3. }
  4. public SparseArray(int initialCapacity) {
  5. initialCapacity = ArrayUtils.idealIntArraySize(initialCapacity);
  6. mKeys = new int[initialCapacity];
  7. mValues = new Object[initialCapacity];
  8. mSize = 0;
  9. }
再来看看它对数据的“增删改查”。

它有两个方法可以添加键值对:

  1. public void put(int key, E value) {}
  2. public void append(int key, E value){}
有四个方法可以执行删除操作:

  1. public void delete(int key) {}
  2. public void remove(int key) {} //直接调用的delete(int key)
  3. public void removeAt(int index){}
  4. public void clear(){}
修改数据起初以为只有setValueAt(int index, E value)可以修改数据,但后来发现put(int key, E value)也可以修改数据,我们查看put(int key, E value)的源码可知,在put数据之前,会先查找要put的数据是否已经存在,如果存在就是修改,不存在就添加。
  1. public void put(int key, E value) {
  2. int i = binarySearch(mKeys, 0, mSize, key);
  3. if (i >= 0) {
  4. mValues[i] = value;
  5. } else {
  6. i = ~i;
  7. if (i < mSize && mValues[i] == DELETED) {
  8. mKeys[i] = key;
  9. mValues[i] = value;
  10. return;
  11. }
  12. if (mGarbage && mSize >= mKeys.length) {
  13. gc();
  14. // Search again because indices may have changed.
  15. i = ~binarySearch(mKeys, 0, mSize, key);
  16. }
  17. …………

 所以,修改数据实际也有两种方法:
  1. public void put(int key, E value)
  2. public void setValueAt(int index, E value)
最后再来看看如何查找数据。有两个方法可以查询取值:

  1. public E get(int key)
  2. public E get(int key, E valueIfKeyNotFound)
其中get(int key)也只是调用了 get(int key,E valueIfKeyNotFound),最后一个从传参的变量名就能看出,传入的是找不到的时候返回的值.get(int key)当找不到的时候,默认返回null。

查看第几个位置的键:

  1. public int keyAt(int index)
有一点需要注意的是,查看键所在位置,由于是采用二分法查找键的位置,所以找不到时返回小于0的数值,而不是返回-1。返回的负值是表示它在找不到时所在的位置。

查看第几个位置的值:

  1. public E valueAt(int index)
查看值所在位置,没有的话返回-1:
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>(转)的更多相关文章

  1. Android 开发性能优化之SparseArray(三)

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

  2. Android 开发性能优化之SparseArray(一)

    多数Android开发者都知道在Android中可以使用HashMap来映射一种对应关系,在java开发中HashMap也算是一种很重要的数据存储结构.然后很多人在Android开发中多数都会用Has ...

  3. Android 开发性能优化之SparseArray(二)

    一.SparseIntArray API SparseIntArrays map integers to integers.  Unlike a normal array of integers, t ...

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

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

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

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

  6. Android 性能优化 SparseArray【转载】

    原文地址:Android学习笔记之性能优化SparseArray 学习内容: 1.Android中SparseArray的使用..   昨天研究完横向二级菜单,发现其中使用了SparseArray去替 ...

  7. Android学习笔记之性能优化SparseArray

    PS:终于考完试了.来一发.微机原理充满了危机.不过好在数据库89分,还是非常欣慰的. 学习内容: 1.Android中SparseArray的使用..   昨天研究完横向二级菜单,发现其中使用了Sp ...

  8. android:应用性能优化SparseArray

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

  9. SparseArray替代HashMap来提高性能

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

随机推荐

  1. ASP.NET实现二维码(QRCode)的创建和读取

    一.项目引用QRCode的DLL文件(ThoughtWorks.QRCode.dll)   二.ASPX页面(两个jquery的js文件请自行去官网下载):   [html]  <html xm ...

  2. J2EE的体系结构是指什么?

    J2EE 即Java2平台企业版,它提供了基于组件的方式来设计.开发.组装和部署企业应用.J2EE使用多层分布式的应用模型,这个多层通常通过三层或四层来实现: 客户层,运行在客户计算机上的组件. We ...

  3. sqlserver2008R2数据库自动备份脚本

    CREATE proc [dbo].[usp_autoBackupDB] @dbname sysname=null --要备份的数据库名,不指定即为全部备份 ,)='d:\' --备份目录路径 ,)= ...

  4. Linux进程托管与守护进程设置

    引言 在上一篇<Linux启动之旅>中,我们了解了Linux启动过程,在该过程的最后一步,init进程拉起/etc/init.d/rcN.d/目录下指定的守护进程(daemon).假若自定 ...

  5. Linux删除以减号开头的文件

    2014年5月5日 10:33:47 原因:文件乱码了,乱码后以减号开头,删不掉 摘抄: 文件系统出现一个文件 -C.html 如何删除/新建?rm -- "-C.html" to ...

  6. OS X 10.11:如何完全停用Time Machine。

    家里的2010年21.5英寸iMac越来越慢,用HFS+分区的1.5TB外置硬盘进行备份时,100G数据经常两三个小时还不能备份完.Time Machine虽然方便,但效率太低,不得不停用. 1. 要 ...

  7. windows安装 Microsoft Visual c++

    第一种方法: 第二种方法: 参考链接 直接给一个2015版本的下载地址 https://blogs.msdn.microsoft.com/pythonengineering/2016/04/11/un ...

  8. 【Android】隐藏底部虚拟按键

    Google的官方文档是: https://developer.android.com/training/system-ui/navigation.html#behind 示例代码 1 View de ...

  9. Chrome插件 postman的使用方法详解!最全面的教程

    一 简介 Postman 是一款功能超级强大的用于发送 HTTP 请求的 Chrome插件 .做web页面开发和测试的人员应该是无人不晓无人不用!其主要特点 特点: 创建 + 测试:创建和发送任何的H ...

  10. ubuntu eclipse 找不到jre文件

    一. 把jdk下的jre文件copy到eclipse安装目录 二. 打开eclipse 重新设计library和工作空间