转载:https://liuzhichao.com/p/832.html

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

sparsearray

意思就是说用SparseArray <E> 来替代,以获取更好性能。老实说,对SparseArray并不熟悉,第一感觉应该是Android提供的一个类。按住Ctrl点击进入SparseArray的源码,果不其然,确定是Android提供的一个工具类。

android_util_sparsearray

单纯从字面上来理解,SparseArray指的是稀疏数组(Sparse array) ,所谓稀疏数组就是数组中大部分的内容值都未被使用(或都为零),在数组中仅有少部分的空间使用。因此造成内存空间的浪费,为了节省内存空间,并且不影响数组中原有的内容值,我们可以采用一种压缩的方式来表示稀疏数组的内容。

假设有一个9*7的数组,其内容如下:

sparsearray_pic1

在此数组中,共有63个空间,但却只使用了5个元素,造成58个元素空间的浪费。以下我们就使用稀疏数组重新来定义这个数组:

sparsearray_pic2.jpg

其中在稀疏数组中第一部分所记录的是原数组的列数和行数以及元素使用的个数、第二部分所记录的是原数组中元素的位置和内容。经过压缩之后,原来需要声明大小为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 &amp;&amp; mValues[i] == DELETED) {
  8. mKeys[i] = key;
  9. mValues[i] = value;
  10. return;
  11. }
  12. if (mGarbage &amp;&amp; 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。

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

查看第几个位置的值:
public E valueAt(int index)
查看值所在位置,没有的话返回-1:
public int indexOfValue(E value)
最后,发现其核心就是折半查找函数(binarySearch),算法设计的很不错。

  1. private static int binarySearch(int[] a, int start, int len, int key) {
  2. int high = start + len, low = start - 1, guess;
  3. while (high - low > 1) {
  4. guess = (high + low) / 2;
  5. if (a[guess] < key)
  6. low = guess;
  7. else
  8. high = guess;
  9. }
  10. if (high == start + len)
  11. return ~(start + len);
  12. else if (a[high] == key)
  13. return high;
  14. else
  15. return ~high;
  16. }

相应的也有SparseBooleanArray,用来取代HashMap <Integer, Boolean> ,SparseIntArray用来取代HashMap <Integer, Integer> ,大家有兴趣的可以研究。

总结:
SparseArray是android里为<Interger,Object> 这样的Hashmap而专门写的类,目的是提高效率,其核心是折半查找函数(binarySearch)。在Android中,当我们需要定义
HashMap <Integer, E> hashMap = new HashMap <Integer, E> ();
时,我们可以使用如下的方式来取得更好的性能.
SparseArray <E> sparseArray = new SparseArray <E> ();

73.Android之SparseArray替代HashMap的更多相关文章

  1. SparseArray替代HashMap来提高性能

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

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

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

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

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

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

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

  5. <转载>Android性能优化之HashMap,ArrayMap和SparseArray

    本篇博客来自于转载,打开原文地址已经失效,在此就不贴出原文地址了,如原作者看到请私信我可用地址,保护原创,人人有责.   Android开发者都知道Lint在我们使用HashMap的时候会给出警告—— ...

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

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

  7. Android 之SparseArray<E>详解

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

  8. 用SparseArray代替HashMap

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

  9. [Android]使用RecyclerView替代ListView(二)

    以下内容为原创,转载请注明: 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/4242541.html 以前写过一篇“[Android]使用Adapte ...

随机推荐

  1. HTML 学习笔记 JavaScript (DOM)

    一 DOM 简介 通过HTML DOM 可以访问JavaScript 文档的所有元素 当网页被加载的时候,浏览器会创建页面的文档对象模型 HTML DOM 模型被构造成对象的树 HTML DOM 树 ...

  2. php的一些小细节

    1.今天看见 $arr3 = array_filter($arr, create_function('$v', 'return strlen($v);')); 作用就是去掉为空的元素,其实当callb ...

  3. repeater 根据输入 返回汉字

    page repeater <asp:Repeater ID="r_scoreCount" runat="server"> <HeaderTe ...

  4. Query on a tree——树链剖分整理

    树链剖分整理 树链剖分就是把树拆成一系列链,然后用数据结构对链进行维护. 通常的剖分方法是轻重链剖分,所谓轻重链就是对于节点u的所有子结点v,size[v]最大的v与u的边是重边,其它边是轻边,其中s ...

  5. MVC中如何设置路由指定默认页

    MVC中怎么设置默认页,在webform中 只要右键设置起始页就可以,但MVC中却没有这个功能,其实MVC更简单 如下: Login是控制器,Index 是动作 在全局Global.asax中改动下即 ...

  6. [转]WampServer localhost 图标不显示解决办法

    FROM : http://blog.warmcolor.net/2011/11/03/wampserver-localhost-%E5%9B%BE%E6%A0%87%E4%B8%8D%E6%98%B ...

  7. Android 的图片异步请求加三级缓存 ACE

    使用xUtils等框架是很方便,但今天要用代码实现bitmapUtils 的功能,很简单, 1 AsyncTask请求一张图片 ####AsyncTask #####AsyncTask是线程池+han ...

  8. 2014-2015-2 《Java程序设计》课程学生博客列表

    20135101 曹钰晶 20135103 王海宁 20135104 刘 帅 20135105 王雪铖 20135109 高艺桐 20135111 李光豫 20135114 王朝宪 20135116 ...

  9. Spring MVC 急速集成 Shiro 实录

    相信有很多的程序员,不愿意进行用户管理这块代码实现. 原因之一,不同的JavaEE 系统,用户管理都会有个性化的实现,逻辑很繁琐. 而且是系统门面,以后背锅的几率非常大,可谓是低收益高风险. 最近在系 ...

  10. .NET MVC AjaxHelper

    我们首先必须开启 非入侵式 Ajax:导入Jquery和unobtrusiveAjax文件 已经默认开启客户端验证 和 非侵入式js <add key="ClientValidatio ...