本篇博客来自于转载,打开原文地址已经失效,在此就不贴出原文地址了,如原作者看到请私信我可用地址,保护原创,人人有责。
 
Android开发者都知道Lint在我们使用HashMap的时候会给出警告——使用SparseArray会优化内存。这可是一件好事情。那现在我们有几个类要学习去使用。比如:ArrayMap和SimpleArrayMap,当然还有各种类型的SparseArray。这篇文章将讲解这些类及它们的原理。
先从如何使用它们开始吧。
   java.util.HashMap<String, String> hashMap = new java.util.HashMap<String, String>(16);
hashMap.put("key", "value");
hashMap.get("key");
hashMap.entrySet().iterator(); android.util.ArrayMap<String, String> arrayMap = new android.util.ArrayMap<String, String>(16);
arrayMap.put("key", "value");
arrayMap.get("key");
arrayMap.entrySet().iterator(); android.support.v4.util.ArrayMap<String, String> supportArrayMap = new android.support.v4.util.ArrayMap<String, String>(16);
supportArrayMap.put("key", "value");
supportArrayMap.get("key");
supportArrayMap.entrySet().iterator(); android.support.v4.util.SimpleArrayMap<String, String> simpleArrayMap = new android.support.v4.util.SimpleArrayMap<String, String>(16);
simpleArrayMap.put("key", "value");
simpleArrayMap.get("key");
//simpleArrayMap.entrySet().iterator(); <- will not compile android.util.SparseArray<String> sparseArray = new android.util.SparseArray<String>(16);
sparseArray.put(10, "value");
sparseArray.get(10); android.util.LongSparseArray<String> longSparseArray = new android.util.LongSparseArray<String>(16);
ongSparseArray.put(10L, "value");
longSparseArray.get(10L); android.util.SparseLongArray sparseLongArray = new android.util.SparseLongArray(16);
sparseLongArray.put(10, 100L);
sparseLongArray.get(10);

接下我们一个一个的讨论。java中的集合基本都是基于数组。在我们了解这些替代类之前我们需要理解HashMap是怎么样工作的。

java.util.HashMap

关于HashMap请参照我另一篇博客,此处不再细说:Android版数据结构与算法(四):基于哈希表实现HashMap核心源码彻底分析

android.util.ArrayMap

ArrayMap 用了两个数组。在它内部用了Object[] mArray来存储Object,还用了int[] mHashes 来存储hashcode,当存储一对键值对的时候。
  • Key/Value会被自动装箱。
  • key会存储在mArray[]的下一个可用的位置。
  • 而value会存储在mArray[]中key的下一个位置。(key和value在mArray中交叉存储)
  • key的哈希值会被计算出来并存储在mHashed[]中。
    当查找一个key的时候:
  • 计算key的hashcode。
  • 在mHashes[]中对这个hashcode进行二分法查找。也就意味着时间复杂度增加到了O(logN)
  • 一旦我们得到了这个哈希值的位置index。我们就知道这个key是在mArray的2index的位置,而value则在2index+1的位置。
    这个ArrayMap还是没能解决自动装箱的问题。当put一对键值对进入的时候,它们只接受Object,但是我们相对于HashMap来说每一次put会少创建一个对象(HashMapEntry)。这是不是值得我们用O(1)的查找复杂度来换呢?对于大多数app应用来说是值得的。

android.support.v4.util.ArrayMap

android.util.ArrayMap只能在api不小于19(Kitkat)的平台才能使用。而Support library则支持在旧平台上提供相同的功能。

android.support.v4.util.SimpleArrayMap

在之前发布的代码片段中你可以看到,这个类没有entrySet()这个支持迭代的方法。如果你查看它的文档,你会发现很java标准集合的方法它都没有。那我们为什么要用它呢。让它失去与其它java容器的相互操作的特性来减小apk的大小。
这样的话,Proguard(代码优化和混沌工具:可能是你代码构建生成的一部分)可以帮你减少大多数没有使用的Collections API代码从而减小你的apk大小。它的内部工作和android.util.ArrayMap是一样的。
 
android.util.SparseArray
和ArrayMap一样,它里面也用了两个数组。一个int[] mKeys和Object[] mValues。从名字都可以看得出来一个用来存储key一个用来保存value的。
当保存一对键值对的时候:
  • key(不是它的hashcode)保存在mKeys[]的下一个可用的位置上。所以不会再对key自动装箱了。
  • value保存在mValues[]的下一个位置上,value还是要自动装箱的,如果它是基本类型。
    查找的时候:
  • 查找key还是用的二分法查找。也就是说它的时间复杂度还是O(logN)
  • 知道了key的index,也就可以用key的index来从mValues中检索出value。
    相较于HashMap,我们舍弃了Entry和Object类型的key,放弃了HashCode并依赖于二分法查找。在添加和删除操作的时候有更好的性能开销。

    KitKat以前的版本用android.support.v4.util.SparseArrayCompat   

android.util.LongSparseArray

SparseArray只接受int类型作为key,而LongSparseArray我们就可以用long作为key。实现原理和SparseArray一致。

android.util.SparseIntArray与android.util.SparseLongArray与android.util.SparseBooleanArray

对于key是int类型而value是int 或者long再或者是boolean,我们可以对应使用SparseIntArray,SparseLongArray ,SparseBooleanArray 。它们使用方式是和SparseArray一样的。它的好处是mValues[]是基本类型的数组。也就意味着无论是key还是value都不用装箱。并且相对于HashMap来说我们节约了3个对象的初始化(Entry,Key和Value),但是我们将查看复杂度从O(1)上升到了O(logN)

结语

使用SparseArray和ArrayMap肯定会减少对象创建的数目。当集合的的数目多达几百个的时候,性能差异也不会很明显(少于50%)。将ArrayMap和SparseArray迁移到新代码中是很有好处的。并且由于方法签名匹配,所以迁移也很容易。

注意:即使它们听起来像数组(Array),ArrayMap和SparseArray不能保证保留它们的插入顺序,在迭代的时候应该注意。

<转载>Android性能优化之HashMap,ArrayMap和SparseArray的更多相关文章

  1. Android性能优化文章转载

    今天看到几篇比较好的文章就转了!(链接如下) 转载注明出处:Sunzxyong Android性能优化之Bitmap的内存优化 Android性能优化之常见的内存泄漏 Android最佳实践之Syst ...

  2. 《Android性能优化》学习笔记链接<转载>

    今天找到一博文汇总了 Android性能优化 比较好的文章 ,本计划全看完,自己再精简下,因篇幅太长,先收藏了,等有时间 再仔细拜读,总结自己的看法:  第一季: http://www.csdn.ne ...

  3. (转载)Google 发布 Android 性能优化典范

    2015年伊始,Google发布了关于Android性能优化典范的专题, 一共16个短视频,每个3-5分钟,帮助开发者创建更快更优秀的Android  App.课程专题不仅仅介绍了Android系统中 ...

  4. android 性能优化

    本章介绍android高级开发中,对于性能方面的处理.主要包括电量,视图,内存三个性能方面的知识点. 1.视图性能 (1)Overdraw简介 Overdraw就是过度绘制,是指在一帧的时间内(16. ...

  5. Android性能优化学习

    工作以来,越来越觉得性能优化的重要性,从技术角度,它甚至成了决定一个app成败的最关键因素.因此,特地花时间去学习专研性能优化的方法. 学习性能优化最便捷的方式便是研读别人有关性能优化的博客,然而网上 ...

  6. 【腾讯Bugly干货分享】Android性能优化典范——第6季

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/580d91208d80e49771f0a07c 导语 这里是Android性能优 ...

  7. Android性能优化典范(转)

    转载自oschina. 2015年伊始,Google发布了关于Android性能优化典范的专题, 一共16个短视频,每个3-5分钟,帮助开发者创建更快更优秀的Android App.课程专题不仅仅介绍 ...

  8. [Android 性能优化系列]降低你的界面布局层次结构的一部分

    大家假设喜欢我的博客,请关注一下我的微博,请点击这里(http://weibo.com/kifile),谢谢 转载请标明出处(http://blog.csdn.net/kifile),再次感谢 原文地 ...

  9. Android 性能优化之工具和优化点总结

    Android性能优化学习 最近公司主抓性能优化工作,借此春风也学习到了许多Android性能优化方面的知识.由于组内队友的给力,优化的成果也是比较喜人.同时也学习和实践了不少知识,特此记录. 1.性 ...

随机推荐

  1. 【转】Python的下划线

    原文: 1. Python中的下划线(译文) 2. [转]关于python中带下划线的变量和函数的意义 总结: 1. 单下划线开头.保护变量,不可被其他包导入使用,除非在__all__声明可以显示引用 ...

  2. 洛谷 P1272 解题报告

    P1272 重建道路 题目描述 一场可怕的地震后,人们用\(N\)个牲口棚\((1≤N≤150\),编号\(1..N\))重建了农夫\(John\)的牧场.由于人们没有时间建设多余的道路,所以现在从一 ...

  3. Java IO流对象、多线程

    Input(读) Output(写)操作 File类 import java.io.File; 将操作系统中的文件.目录(文件夹).路径.封装成File对象 提供方法,操作系统中的内容.File与系统 ...

  4. 读《图解HTTP》有感-(与HTTP协作的WEB服务器)

    写在前面 Web服务器一般指网站服务器,是指驻留于因特网上某种类型计算机的程序,可以向浏览器等Web客户端提供文档: 一台web服务器可以搭建多个独立域名的web网站,也可以作为通信路径(路由)上的中 ...

  5. Excel常用的格式处理

    你有没有碰到在Excel中设置了行高自适应后,部分行的行高太小,整体界面不美观的问题呢? 你有没有碰到Excel中的各个sheet页中的各列内容中都有不同个数的回车换行符,内容看起来参差不齐,不美观呢 ...

  6. Spring 的IOC和AOP总结

    Spring 的IOC和AOP IOC 1.IOC 许多应用都是通过彼此间的相互合作来实现业务逻辑的,如类A要调用类B的方法,以前我们都是在类A中,通过自身new一个类B,然后在调用类B的方法,现在我 ...

  7. 网络营销行业十大看了就想吐的“滥词”

    网络营销行业在国内的互联网界已"猖獗"数年之久,它是一个让企业爱让用户恨的行业.有互联网的地方,就有网络营销的机会,有了机会就有了相关产业的存在,只不过是业大业小的问题.但是随着互 ...

  8. 分布式计算框架Gearman原理详解

    什么是Gearman? Gearman提供了一个通用的应用程序框架,用于将工作转移到更适合于工作的其他机器或流程.它允许你并行工作,负载平衡处理,并在语言间调用函数.它可用于从高可用性网站到传输数据库 ...

  9. Linux ftrace框架介绍及运用

    目录: 1. ftrace背景 2. 框架介绍 3. 主要代码分析 4. ftrace的配置和使用 5. ftrace相关工具 在日常工作中,经常会需要对内核进行Debug.或者进行优化工作.一些简单 ...

  10. Volley 图片加载相关源码解析

    转载请标明出处: http://blog.csdn.net/lmj623565791/article/details/47721631: 本文出自:[张鸿洋的博客] 一 概述 最近在完善图片加载方面的 ...