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  
5 public SparseArray(int initialCapacity) {
6     initialCapacity = ArrayUtils.idealIntArraySize(initialCapacity);
7  
8     mKeys = new int[initialCapacity];
9     mValues = new Object[initialCapacity];
10     mSize = 0;
11 }

再来看看它对数据的“增删改查”。

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

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  
4     if (i >= 0) {
5         mValues[i] = value;
6     else {
7         i = ~i;
8  
9         if (i < mSize && mValues[i] == DELETED) {
10             mKeys[i] = key;
11             mValues[i] = value;
12             return;
13         }
14  
15         if (mGarbage && mSize >= mKeys.length) {
16             gc();
17  
18             // Search again because indices may have changed.
19             i = ~binarySearch(mKeys, 0, mSize, key);
20         }
21         …………

所以,修改数据实际也有两种方法:

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, int key) {
2     int high = 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     else if (a[high] == key)
16         return high;
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>();

Android应用性能优化之使用SparseArray替代HashMap的更多相关文章

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

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

  2. Android应用性能优化(转)

    人类大脑与眼睛对一个画面的连贯性感知其实是有一个界限的,譬如我们看电影会觉得画面很自然连贯(帧率为24fps),用手机当然也需要感知屏幕操作的连贯性(尤其是动画过度),所以Android索性就把达到这 ...

  3. android app性能优化大汇总

    这里根据网络上各位大神已经总结的知识内容做一个大汇总,作为记录,方便后续“温故知新”. 性能指标: (1)使用流畅度:  图片处理器每秒刷新的帧数(FPS),可用来指示页面是否平滑的渲染.高的帧率可以 ...

  4. Android客户端性能优化(魅族资深工程师毫无保留奉献)

    本文由魅族科技有限公司资深Android开发工程师degao(嵌入式企鹅圈原创团队成员)撰写,是degao在嵌入式企鹅圈发表的第一篇原创文章,毫无保留地总结分享其在领导魅族多个项目开发中的Androi ...

  5. Android APP 性能优化的一些思考

    说到 Android 系统手机,大部分人的印象是用了一段时间就变得有点卡顿,有些程序在运行期间莫名其妙的出现崩溃,打开系统文件夹一看,发现多了很多文件,然后用手机管家 APP 不断地进行清理优化 ,才 ...

  6. 包建强的培训课程(9):Android App性能优化

    v\:* {behavior:url(#default#VML);} o\:* {behavior:url(#default#VML);} w\:* {behavior:url(#default#VM ...

  7. Android app 性能优化的思考--性能卡顿不好的原因在哪?

    说到 Android 系统手机,大部分人的印象是用了一段时间就变得有点卡顿,有些程序在运行期间莫名其妙的出现崩溃,打开系统文件夹一看,发现多了很多文件,然后用手机管家 APP 不断地进行清理优化 ,才 ...

  8. Android开发性能优化总结(一)

    安卓开发应用首先要讲究良好的用户体验,如果一款软件卡顿现象严重,不流畅,经常崩溃,那么将给用户带来极不良好的体验,从而损失用户. 在实际开发和学习中,我总结了一下关于安卓性能的优化,供大家参考交流. ...

  9. Android应用性能优化系列视图篇——隐藏在资源图片中的内存杀手

    图片加载性能优化永远是Android领域中一个无法绕过的话题,经过数年的发展,涌现了很多成熟的图片加载开源库,比如Fresco.Picasso.UIL等等,使得图片加载不再是一个头疼的问题,并且大幅降 ...

随机推荐

  1. Android WebView 获取网页的标题

    final TextView txtTitle = (TextView) findViewById(R.id.txtTitle); final WebView webView = (WebView)f ...

  2. UnityShader之Shader格式篇【Shader资料1】

    关于Shader,在Unity里面我们一般叫做ShaderLab,只要你的职业是与渲染搭边,Unity就与ShaderLab有着直接的关联,你都应该试着去学会它,其实我们在新手未有入门的时候,我们总是 ...

  3. .NET下单文件的上传处理

    ASP.NET的单文件上传使用控件 <asp:FileUpload ID="upmess" runat="server" Width="248p ...

  4. eval 为什么加括号

    <!DOCTYPE html> <html> <head> <title>eval学习</title> <script type=&q ...

  5. Effective Java 68 Prefer executors and tasks to threads

    Principle The general mechanism for executing tasks is the executor service. If you think in terms o ...

  6. JavaScript Patterns 3.2 Custom Constructor Functions

    When you invoke the constructor function with new, the following happens inside the function: • An e ...

  7. javascript/jquery 常见功能实现(持续更新...)

    1. input 只能输入整数数字和字母 $(document).on('keyup','#no',function(){ var val = $.trim($(this).val()); if(va ...

  8. PL/SQL之--包

    一.包 包是一组相关过程.函数.常量.变量.游标.异常等PL/SQL程序设计元素的组合.它类似于C++和Java中的类,其中变量相当于类中的成员变量,过程和函数相当于类中的方法.通过使用包,可以使开发 ...

  9. golang中os/exec包用法

    exec包执行外部命令,它将os.StartProcess进行包装使得它更容易映射到stdin和stdout,并且利用pipe连接i/o. 1.func LookPath(file string) ( ...

  10. android适配器及监听点击和滚动在ListView中的使用

    package com.example.demon08; import java.util.ArrayList;import java.util.HashMap;import java.util.Li ...