SparseArray HashMap 稀疏数组 二分法
简介
HashMap是java里比较常用的一个集合类,我们常用其来缓存一些处理后的结果,但是在Android项目中,Eclipse却给出了一个 performance 警告。意思就是说用SparseArray<E>来替代,以获取更好性能。按住Ctrl点击进入SparseArray的源码,可以看出他是Android提供的一个工具类。路径为:android.util.SparseArray。SparseArray是android里为<Interger,Object>这样的HashMap而专门写的类,目的是提高效率,其核心是折半查找函数(binarySearch)。SparseBooleanArray、SparseIntArray、SparseLongArray都是SparseArray的特殊形式(不带泛型),其key为Interget,value为特定的类型。在Android中,当我们需要定义HashMap<Integer,E>时,我们可以使用SparseArray<E>来取得更好的性能。总体来说,它们都是类似map这样key-value的存储方式,但是由于查找的算法不一样,因此效率也各不同。但要明白,没有说哪个一定是最好的,只有根据不同需求在不同场景去应用,才能获取较优的结果。
官方文档
/* SparseArrays 利用integer去管理object对象。不像一个正常的object对象数组,它能在索引数中快速的查找到所需的结果。(这* 句话是意译,原意是能在众多索引数中“撕开一个缺口”,为什么原文这么表达?下面会慢慢说清楚。)它比HashMap去通过Integer索引* 查找object对象时在内存上更具效率,不仅因为它避免了用来查找的自动“装箱”的keys,并且它的数据结构不依赖额外的对象去* 各个映射中查找匹配。** 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.** 请注意,这个容器会保持它的映射关系在一个数组的数据结构中,通过二分检索法去查找key。(这里我们终于知道,为何这个工具类中,* 提供的添加映射关系的操作中,key的类型必须是integer。因为二分检索法,将从中间“切开”,integer的数据类型是实现这种检索过程的保证。)** 如果保存大量的数据,这种数据结构是不适合的,换言之,SparseArray这个工具类并不应该用于存储大量的数据。这种情况下,它的效率* 通常比传统的HashMap更低,因为它的查找方法并且增加和移除操作(任意一个操作)都需要在数组中插入和删除(两个步骤才能实现)。** 如果存储的数据在几百个以内,它们的性能差异并不明显,低于50%。** (OK,那么光看Android官方的介绍我们就有初步结论了,大量的数据我们相对SparseArray会优先选择HashMap,如果数据在几百个这个数目,* 那么选择它们任意一个去实现区别不大,如果数量较少,就选择SparseArray去实现。 其实如果我们理解了二分法,就很容易了SparseArray的* 实现原理,以及SparseArray和HashMap它们之间的区别了。)** <p>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%.</p>** 为了提高性能,这个容器包含了一个实现最优的方法:当移除keys后为了立刻使它的数组紧密,它会“遗留”已经被移除(标记了要删除)的条目(entry) 。* 所被标记的条目(entry)(还未被当作垃圾回收掉前)可以被相同的key复用,也会在垃圾回收机制当作所有要回收的条目的一员被回收,从而使存储的数组更紧密。** (我们下面看源码就会发现remove()方法其实是调用delete()方法的。印证了上面这句话所说的这种优化方法。* 因为这样,能在每次移除元素后一直保持数组的数据结构是紧密不松散的。)** 垃圾回收的机制会在这些情况执行:数组需要扩充,或者映射表的大小被恢复,或者条目值被重新检索后恢复的时候。** <p>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.</p>** 当调用keyAt(int)去获取某个位置的key的键的值,或者调用valueAt(int)去获取某个位置的值时,可能是通过迭代容器中的元素* 去实现的。** <p>It is possible to iterate over the items in this container using* {@link #keyAt(int)} and {@link #valueAt(int)}. Iterating over the keys using* <code>keyAt(int)</code> 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 <code>valueAt(int)<code>.</p>*/public class SparseArray<E> implements Cloneable
稀疏数组
单纯从字面上来理解,SparseArray指的是稀疏数组(Sparse array),所谓稀疏数组就是数组中大部分的内容值都未被使用(或都为零),在数组中仅有少部分的空间使用。因此造成内存空间的浪费,为了节省内存空间,并且不影响数组中原有的内容值,我们可以采用一种压缩的方式来表示稀疏数组的内容。假设有一个9*7的数组,其内容如下:在此数组中,共有63个空间,但却只使用了5个元素,造成58个元素空间的浪费。以下我们就使用稀疏数组重新来定义这个数组:在稀疏数组中,第一部分所记录的是原数组的【行数】、【列数】以及【元素的使用个数】,第二部分所记录的是所使用的元素在原数组中的【位置】和【内容】。经过压缩之后,原来需要声明大小为63的数组,而使用压缩后,只需要声明大小为6*3的数组,仅需18个存储空间。
SparseIntArray API
public class SparseIntArray implements Cloneable {public SparseIntArray()//默认的大小是10public SparseIntArray(int initialCapacity)public SparseIntArray clone()public int get(int key)//当找不到的时候,默认返回null。public int get(int key, int valueIfKeyNotFound)//当找不到的时候,返回valueIfKeyNotFoundpublic void delete(int key)public void removeAt(int index)//直接调用的delete(int key)public void put(int key, int value)//在put数据之前,会先查找要put的数据是否已经存在,如果存在就是修改,不存在就添加public int size()public int keyAt(int index)//采用二分法查找键的位置,所以找不到时返回小于0的数值,而不是返回-1。返回的负值是表示它在找不到时所在的位置public int valueAt(int index)public int indexOfKey(int key)public int indexOfValue(int value)//查看值所在位置,没有的话返回-1public void clear()public void append(int key, int value)public String toString()
SparseArray HashMap 稀疏数组 二分法的更多相关文章
- JAVA描述算法和数据结构(01):稀疏数组和二维数组转换
本文源码:GitHub·点这里 || GitEE·点这里 一.基本简介 1.基础概念 在矩阵中,若数值为0的元素数目远远多于非0元素的数目,并且非0元素分布没有规律时,则称该矩阵为稀疏矩阵:与之相反, ...
- 你听过稀疏数组(sparseArray)吗?
稀疏数组(sparseArray) 基本介绍 当一个数组中大部分元素为0,或者为同一个值的数组时,可以使用稀疏数组来保存该数组. 稀疏数组的处理方法是: 1.记录数组一共有几行几列,有多少个不同的值 ...
- 稀疏数组SparseArray
1 实际需求 1.1 需求提出 编写五子棋程序,有存盘退出和续上盘的功能. 实现思路: 存盘退出: 定义一个二维数组,默认值是0,黑子表示1,蓝子表示2,然后将二维数组通过流存储到文件中. 换言之:五 ...
- C#数据结构与算法系列(二):稀疏数组(SparseArray)
1.介绍 当一个数组中大部分元素为0,或者为同一个值的数组时,可以使用稀疏数组来保存该数组. 稀疏数组的处理方法是: 1.记录数组一共有几行几列,有多少个不同的值 2.把具有不同值的元素的 ...
- 稀疏数组(java实现)
1.稀疏数组 当一个数组中大部分元素为0,或者为同一个值的数组时,可以使用稀疏数组来保存该数组. 稀疏数组的处理方法是: 1.1记录数组一共有几行几列,有多少个不同的值 1.2把具有不同值的元素的行列 ...
- java实现稀疏数组压缩
package sparseArray; public class SparseArray { public static void main(String[] args) { // TODO Aut ...
- Java数据结构之稀疏数组(Sparse Array)
1.需求 编写的五子棋程序中,有存盘退出和续上盘的功能.因为该二维数组的很多值是默认值0,因此记录了很多没有意义的数据,为了压缩存储所以采用稀疏数组. 2.基本介绍 当一个数组中大部分元素为0,或者为 ...
- 【学习总结】java数据结构和算法-第三章-稀疏数组和队列
相关链接 [学习总结]尚硅谷2019java数据结构和算法 github:javaDSA 目录 稀疏数组 队列 稀疏数组 稀疏数组介绍 图示 应用实例 代码实现 SparseArray.java:与二 ...
- 数据结构 二维数组-->稀疏数组-->二维数组
稀疏数组基本概念: 稀疏数组应用场景: 当一个数组大部分的元素为"0",或者为同一个值的数组时,可以使用稀疏数组来保存该数组 处理方法: 1>记录数组一共有几行几列,有多少不 ...
随机推荐
- 【USACO 3.1.6】邮票
[描述] 已知一个N枚邮票的面值集合(如,{1分,3分})和一个上限K ——表示信封上能够贴K张邮票.计算从1到M的最大连续可贴出的邮资. 例如,假设有1分和3分的邮票:你最多可以贴5张邮票.很容易贴 ...
- C#实现的异步Socket服务器
介绍 我最近需要为一个.net项目准备一个内部线程通信机制. 项目有多个使用ASP.NET,Windows 表单和控制台应用程序的服务器和客户端构成. 考虑到实现的可能性,我下定决心要使用原生的soc ...
- Android学习----ADB
adb是什么?:adb的全称为Android Debug Bridge,就是起到调试桥的作用.通过adb我们可以在Eclipse中方面通过DDMS来调试Android程序,说白了就是debug工具.a ...
- js 联系电话验证实现
var str=$('#tele').val(); var regPartton=/1[3-8]+\d{9}/; ...
- Python新手学习基础之数据结构-列表1
创建一个列表 讲完了序列,我们现在来讲讲Python中最常见的一种序列数据类型--列表. 列表创建的语法是: list_name = [item1, item2, item3, .......] 列表 ...
- python numpy 使用笔记 矩阵操作
(原创文章转载请标注来源) 在学习机器学习的过程中经常会用到矩阵,那么使用numpy扩展包将是不二的选择 建议在平Python中用多维数组(array)代替矩阵(matrix) 入门请考 http:/ ...
- 《30天自制操作系统》读书笔记(3) 引入C语言
这一次的学习相当曲折, 主要是因为粗心, Makefile里面的错误导致了文件生成出现各种奇奇怪怪的问题, 弄得心力交瘁, 因此制作过程还是尽量按着作者的路子来吧. 作者提供的源码的注释在中文系统下是 ...
- mysqldump 一些参数体验
mysqldump -uroot -p'xxx' -R --single-transaction --master-data=2 zjzc>$TODAY_DIR/zjzc/zjzc_${TODA ...
- 关于索引degree设置的问题
--并行查询 可以使用并行查询的情况 1. Full table scans, full partition scans, and fast full index scans 2. Index ful ...
- Makefile中的wildcard和patsubst
makefile 里的函数跟它的变量很相似——使用的时候,你用一个 $ 符号跟开括号,函数名,空格后跟一列由逗号分隔的参数,最后用关括号结束. 例如,在 GNU Make 里有一个叫 'wild ...


