为什么要用SparseArray来替换HashMap?

博文背景:

在Android 中使用HashMap 的时候看到过提示。

HashMap<Integer,Object> mp = new HashMap<Integer,Object>(); 

提示:Use new SparseArray<Object>(...) instead for better performance意思是,使用 SparseArray 将获得更好的性能
(注:这个提示我再eclipse 中见过,而在studio 中并没有看到过这种提示)

查阅网上资料关于SparseArray文档介绍,分析如下(ps:借鉴网上大佬的翻译):

SparseArrays map integers to Objects. Unlike a normal array of Objects, there can be gaps in the indices. It is intended to be more memory efficient than using a HashMap to map Integers to Objects, both because it avoids auto-boxing keys and its data structure doesn’t rely on an extra entry object for each mapping.

(译文+个人理解)
SparseArrays不同于普通的对象数组。there can be gaps in the indices.(指针中能够存在空白?注:这句我不太理解,不知道怎样翻译,是说SparseArrays 是不连续存储?)。它的目的是比使用从整数映射对象的HashMap(简单来说就是 HashMap<Integer,Object>)有更有效的使用内存。

同一时候也避免auto-boxing(自己主动装箱)(注:auto-boxing(自己主动装箱):将原始类型封装为对象类型。比方把int类型封装成Integer类型。)和数据结构对每条映射不依赖额外的Entry 对象(注:这里是和HashMap做的对照。在HashMap有须要引入Entry<K,V>,而SparseArrays比較简单,里面是两个一维数组 int[] mKeys; 和 Object[] mValues)

Note that this container keeps its mappings in an array data structure, using a binary search to find keys. The implementation is not intended to be appropriate for data structures that may contain large numbers of items. It is generally slower than a traditional HashMap, since lookups require a binary search and adds and removes require inserting and deleting entries in the array. For containers holding up to hundreds of items, the performance difference is not significant, less than 50%.

注意,这个容器在数组数据结构中维持一个映射关系。使用二分查找法来找到key.它的目标不是为了适应数据结构中包括大量数据的情况。

通常情况下要比传统的HashMap慢,由于查找是用二分查找法搜索,加入和删除须要对数组进行加入和删除。

对于有几百条的数据的容器。性能差异不大,不超过50%(注:这里我理解的是, SparseArrays 的优势更体如今小数量上)

To help with performance, the container includes an optimization when removing keys: instead of compacting its array immediately, it leaves the removed entry marked as deleted. The entry can then be re-used for the same key, or compacted later in a single garbage collection step of all removed entries. This garbage collection will need to be performed at any time the array needs to be grown or the the map size or entry values are retrieved.

为了提高性能,该容器提供了一个优化:当删除key键时。不是立刻删除这一项,而是留下须要删除的选项给一个删除的标记。

该条目能够被又一次用于同样的key,或者被单个垃圾收集器逐步删除完所有的条目后压缩。在不论什么时候。当数组须要增长(注:这里我理解为 put、append之类的操作)或者Map 的长度、entry的value须要被检索的时候,该垃圾收集器就会运行(注:这里能够从代码中发现。google在相应的方法中调用 gc() 方法)。

It is possible to iterate over the items in this container using

  • {@link #keyAt(int)} and {@link #valueAt(int)}. Iterating over the keys using
  • keyAt(int) with ascending values of the index will return the
  • keys in ascending order, or the values corresponding to the keys in ascending
  • order in the case of valueAt(int).

在此使用此容器时,能够迭代遍历当中的item.. keyAt(int) 返回升序下的key .
valueAt(int) 返回升序状态下。key 相应的value值。

与HashMap比较优点?

key,value 类型的比較

HashMap | key:随意类型 | value:随意类型
SparseArray | key:Integer | value:随意类型
SparseBooleanArray | key:Integer | value:Boolean类型。
SparseIntArray | key:Integer | value:Integer类型。
LongSparseArray | key:Long | value:随意类型

依据需求的不同,找到合适的方法才是上上策。

内部存储的比較

SparseArray |: int[] mkeys和 Object[] mvalues 来存储key和value
HashMap | : 内部存储必须使用Entry<k,v>

其他分析

  • 创建数据

以10000条数据为例。HashMap用去约13.2M内存,SparseArray共用去 8.626M内存。

  • 数据插入

在正序插入数据时候,SparseArray比HashMap要快一些;HashMap无论是倒序还是正序开销差点儿是一样的。可是SparseArray的倒序插入要比正序插入要慢很多,为什么呢?
原因:SparseArray在检索数据的时候使用的是二分查找,所以每次插入新数据的时候SparseArray都须要又一次排序,所以逆序是最差情况。

  • 数据检索

SparseArray中存在须要检索的下标时。SparseArray的性能略胜一筹可是当检索的下标比較离散时,SparseArray须要使用多次二分检索,性能显然比hash检索方式要慢一些了。

  • 接口实现

    HashMap实现了Cloneable, Serializable SparseArray 实现了Cloneable 接口,也就是说SparseArray 是不支持序列化的。

  • 运行速度上比较,见大神分析:(传送门)

源码就不粘贴了,分析部分代码:

<pre><code>
/**

  • Adds a mapping from the specified key to the specified value,

  • replacing the previous mapping from the specified key if there

  • was one.
    通过指定的key和value加入一个键值对,假设这个位置已经存在一个了,则替换掉
    */
    public void put(int key, E value) {
    int i = ContainerHelpers.binarySearch(mKeys, mSize, key);

    if (i >= 0) {
    mValues[i] = value;
    } else {
    i = ~i;

     if (i < mSize && mValues[i] == DELETED) {
         mKeys[i] = key;
         mValues[i] = value;
         return;
     }
    
     if (mGarbage && mSize >= mKeys.length) {
         gc();
    
         // Search again because indices may have changed.
         i = ~ContainerHelpers.binarySearch(mKeys, mSize, key);
     }
    
     mKeys = GrowingArrayUtils.insert(mKeys, mSize, i, key);
     mValues = GrowingArrayUtils.insert(mValues, mSize, i, value);
     mSize++;
    

    }
    }

/**

  • Puts a key/value pair into the array, optimizing for the case where
  • the key is greater than all existing keys in the array.
    通过指定的key和value加入一个键值对,在原有的基础上添加
    */
    public void append(int key, E value) {
    if (mSize != 0 && key <= mKeys[mSize - 1]) {
    put(key, value);
    return;
    }
    </code></pre>

仅用于记录备忘分享,如有版权问题烦请私信!谢谢

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,230评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,261评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,089评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,542评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,542评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,544评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,922评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,578评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,816评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,576评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,658评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,359评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,937评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,920评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,859评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,381评论 2 342

推荐阅读更多精彩内容