SparseArray是Android框架独有的类,在标准的JDK中不存在这个类。它要比 HashMap 节省内存,某些情况下比HashMap性能更好,按照官方问答的解释,主要是因为SparseArray不需要对key和value进行auto-boxing(将原始类型封装为对象类型,比如把int类型封装成Integer类型),结构比HashMap简单(SparseArray内部主要使用两个一维数组来保存数据,一个用来存key,一个用来存value)不需要额外的额外的数据结构(主要是针对HashMap中的HashMapEntry而言的)。是骡子是马得拉出来遛遛,下面我们就通过几段程序来证明SparseArray在各方面表现如何,下面的试验结果时在我的Hike X1(Android 4.2.2)手机上运行得出的。

代码1:

int MAX = 100000;long start = System.currentTimeMillis();HashMap hash = new HashMap();for (int i = 0; i < MAX; i++) { hash.put(i, String.valueOf(i));}long ts = System.currentTimeMillis() - start;

代码2:

int MAX = 100000;long start = System.currentTimeMillis();SparseArray sparse = new SparseArray();for (int i = 0; i < MAX; i++) { sparse.put(i, String.valueOf(i));}long ts = System.currentTimeMillis() - start;

我们分别在long start处和long ts处设置断点,然后通过DDMS工具查看内存使用情况。

代码1中,我们使用HashMap来创建100000条数据,开始创建前的系统内存情况为:

创建HashMap之后,应用内存情况为:

可见创建HashMap用去约 13.2M内存。

再看 代码2,同样是创建100000条数据,我们用SparseArray来试试,开始创建前的内存使用情况为:

创建SparseArray之后的情况:

创建SparseArray共用去 8.626M内存。

可见使用 SparseArray 的确比 HashMap 节省内存,大概节省 35%左右的内存。

我们再比较一下插入数据的效率如何,我们在加两段代码(主要就是把插入顺序变换一下,从大到小插入):

代码3:

int MAX = 100000;long start = System.currentTimeMillis();HashMap hash = new HashMap();for (int i = 0; i < MAX; i++) { hash.put(MAX - i -1, String.valueOf(i));}long ts = System.currentTimeMillis() - start;

代码4:

int MAX = 100000;long start = System.currentTimeMillis();SparseArray sparse = new SparseArray();for (int i = 0; i < MAX; i++) { sparse.put(MAX - i -1, String.valueOf(i));}long ts = System.currentTimeMillis() - start;

我们分别把这4代码分别运行5次,对比一下ts的时间(单位毫秒):#代码1代码2代码3代码4110750ms7429ms10862ms90527ms

210718ms7386ms10711ms87990ms

310816ms7462ms11033ms88259ms

410943ms7386ms10854ms88474ms

510671ms7317ms10786ms90630ms

通过结果我们看出,在正序插入数据时候,SparseArray比HashMap要快一些;HashMap不管是倒序还是正序开销几乎是一样的;但是SparseArray的倒序插入要比正序插入要慢10倍以上,这时为什么呢?我们再看下面一段代码:

代码5:

SparseArray sparse = new SparseArray(3);sparse.put(1, "s1");sparse.put(3, "s3");sparse.put(2, "s2");

我们在Eclipse的debug模式中,看Variables窗口,如图:

及时我们是按照1,3,2的顺序排列的,但是在SparseArray内部还是按照正序排列的,这时因为SparseArray在检索数据的时候使用的是二分查找,所以每次插入新数据的时候SparseArray都需要重新排序,所以代码4中,逆序是最差情况。

下面我们在简单看下检索情况:

代码5:

long start4search = System.currentTimeMillis();for (int i = 0; i < MAX; i++) { hash.get(33333); //针对固定值检索}long end4search = System.currentTimeMillis() - start4search;

代码6:

long start4search = System.currentTimeMillis();for (int i = 0; i < MAX; i++) { hash.get(i); //顺序检索}long end4search = System.currentTimeMillis() - start4search;

代码7:

long start4search = System.currentTimeMillis();for (int i = 0; i < MAX; i++) { sparse.get(33333); //针对固定值检索}long end4search = System.currentTimeMillis() - start4search;

代码8:

long start4search = System.currentTimeMillis();for (int i = 0; i < MAX; i++) { sparse.get(i); //顺序检索}long end4search = System.currentTimeMillis() - start4search;

表1:#代码5代码6代码7代码814072ms4318ms3442ms3390ms

24349ms4536ms3402ms3420ms

34599ms4203ms3472ms3376ms

44149ms4086ms3429ms3786ms

54207ms4219ms3439ms3376ms

代码9,我们试一些离散的数据。

//使用Foo为了避免由原始类型被自动封装(auto-boxing,比如把int类型自动转存Integer对象类型)造成的干扰。class FOO{ Integer objKey; int intKey;}...int MAX = 100000;HashMap hash = new HashMap();SparseArray sparse = new SparseArray();for (int i = 0; i < MAX; i++) { hash.put(i, String.valueOf(i)); sparse.put(i, String.valueOf(i));}List keylist4search = new ArrayList();for (int i = 0; i < MAX; i++) { FOO f = new FOO(); f.intKey = i; f.objKey = Integer.valueOf(i); keylist4search.add(f);}long start4search = System.currentTimeMillis();for (int i = 0; i < MAX; i++) { hash.get(keylist4search.get(i).objKey);}long end4searchHash = System.currentTimeMillis() - start4search;long start4search2 = System.currentTimeMillis();for (int i = 0; i < MAX; i++) { sparse.get(keylist4search.get(i).intKey);}long end4searchSparse = System.currentTimeMillis() - start4search2;

代码9,运行5次之后的结果如下:

表2:#end4searchHashend4searchSparse12402ms4577ms

22249ms4188ms

32649ms4821ms

42404ms4598ms

52413ms4547ms

从上面两个表中我们可以看出,当SparseArray中存在需要检索的下标时,SparseArray的性能略胜一筹(表1)。但是当检索的下标比较离散时,SparseArray需要使用多次二分检索,性能显然比hash检索方式要慢一些了(表2),但是按照官方文档的说法性能差异不是很大,不超过50%( For containers holding up to hundreds of items, the performance difference is not significant, less than 50%.)

总体而言,在Android这种内存比CPU更金贵的系统中,能经济地使用内存还是上策,何况SparseArray在其他方面的表现也不算差(另外,SparseArray删除数据的时候也做了优化——使用了延迟整理数组的方法,可参考官方文档SparseArray,读者可以自行把代码9中的hash.get和sparse.get改成hash.remove和sparse.delete试试,你会发现二者的性能相差无几)。而且,使用SparseArray代替HashMap也是官方推荐的做法,在Eclipse中也会提示你优先使用SparseArray,如图:

fpga运算服务器_SparseArray替代HashMap来提高性能相关推荐

  1. fpga运算服务器_当FPGA也成为一种服务,你还在顾虑什么?

    [IT168 资讯]这几天,已经退役的AlphaGo又强行刷了一波头条,不是又跟哪位世界高手对决,而是"新狗"通过无监督式学习,仅用3天时间就战胜了李世石版的AlphaGo,然后用 ...

  2. fpga运算服务器_一张图了解CPU、GPU、ASIC、FPGA性能、功耗效率、灵活性

    ​CPU:中央处理器(Central Processing Unit,CPU):通用芯片,主要生产厂家如intel.AMD等,用于PC.服务器等领域.CPU作为通用芯片,可以用来做很多事情,灵活性最高 ...

  3. 国内首款 FPGA 云服务器,性能是通用 CPU 服务器 30 倍以上

    2019独角兽企业重金招聘Python工程师标准>>> 版权声明:本文由薛梁 原创文章,转载请注明出处:  文章原文链接:https://www.qcloud.com/communi ...

  4. 国内首款FPGA云服务器,性能是通用CPU服务器30倍以上

    FPGA(Field Programmable Gate Array)现场可编程门阵列,作为ASIC领域中的一种半定制电路而出现已有30年的历史了,它既解决了定制电路的无法改变功能的不足,又克服了原有 ...

  5. 华为服务器gpu卡型号,GPU运算服务器推荐

    GPU运算服务器推荐 内容精选 换一换 只有运行中的云服务器才允许用户登录.Windows操作系统用户名"Administrator".忘记密码,请先通过"重置密码&qu ...

  6. 企业网络推广下微软服务器浸泡于液体试图提高服务器的散热与性能

    众所周知,随着互联网时代的飞速发展,服务器市场也得到庇荫,当下的互联网科技公司哪家还没有几台服务器了?互联网科技公司需要的大数据与计算大部分都是通过服务器来进行的,而为了防止服务器崩溃也要估计到其自身 ...

  7. 微服务架构 性能提升_如何通过无服务器架构提高性能

    微服务架构 性能提升 by Domenico Angilletta 通过多梅尼科·安吉列塔(Domenico Angilletta) 如何通过无服务器架构提高性能 (How to boost your ...

  8. vmware虚拟化服务器cpu超线程,VMware vSphere的配置方法最佳方案从而提高性能

    VMware相信使用过VMware的用户都了解,它目前已经为上百万用户提供了完美的虚拟化解决方案,VMware vSphere作为行业最佳的虚拟化产品,但不管任何虚拟化策略的部署都需要软硬件的强力配合 ...

  9. 阿里云FPGA云服务器规格配置、性能及价格表

    阿里云FPGA云服务器一款提供了现场可编程门阵列(FPGA)的计算实例,FPGA云服务器是基于阿里云弹性计算框架,用户可以几分钟内轻松创建FPGA实例,创建自定义的专用硬件加速器.InstanceTy ...

最新文章

  1. PubChem分子库
  2. linux高编线程-------线程的创建,终止
  3. php支付宝h5 app,H5网站接入支付宝的支付接口
  4. [zz]正则表达式使用详解
  5. ◆[转]瓶子生日密码之2月2日
  6. 不安全的发布 java_如何在没有安全警告的情况下发布Java Web S...
  7. [Python爬虫] Selenium+Phantomjs动态获取CSDN下载资源信息和评论
  8. Win7提示文件太大无法放入回收站怎么办
  9. 【OpenCV学习笔记】2.1OpenCV基本数据类型
  10. SEO按天关键词计费排名查询系统源码
  11. CentOs基础操作指令(vim、关机)
  12. 手机自带计算机的功能,手机上的这3个小功能,比电脑方便好用,你知道吗?...
  13. arm的bin二进制代码分析
  14. Oracle 11gR2光钎链路切换crs服务发生crash
  15. conan-transit服上的库列表
  16. android 权限整理
  17. 【云原生之k8s】k8s基础详解
  18. Java——通过Java代码启动批处理文件(一)
  19. 读书随想2 - 格鲁夫给经理人的第一课
  20. python灰帽子学习感想

热门文章

  1. 敢闯会创,第七届中国国际“互联网+”双创大赛腾讯广告产业命题等你来战!
  2. Sampled Softmax,你真的会用了吗?
  3. java jobkey_Java JobBuilder.newJob方法代码示例
  4. linux同内核覆盖,Linux内核代码覆盖率 – GCOV
  5. Leetcode每日一题:861.score-after-flipping-matrix(反转矩阵后的得分)
  6. 吴恩达机器学习 12.异常检测
  7. POJ - 3984
  8. 吴恩达深度学习神经网络基础编程作业Python Basics with Numpy
  9. cts测试linux指令skip,linux – dd命令中seek和skip之间有什么区别?
  10. 关于滑轮组的计算机知识点,初中物理:滑轮及滑轮组知识点总结