数据结构:

    int[] mHashes;Object[] mArray;

为两个数组实现,mHashes 负责记录Key的hash,key的hash所在的位置index,在mArray对应的位置 index2 为Key index2 + 1 为value
mHashes 里面的元素是经过排序的 支持二分查找

增删改查

Put操作:

    public V put(K key, V value) {final int osize = mSize;final int hash;int index;if (key == null) {hash = 0;index = indexOfNull();} else {hash = mIdentityHashCode ? System.identityHashCode(key) : key.hashCode();index = indexOf(key, hash);}//已经存在相同的keyif (index >= 0) {index = (index<<1) + 1;final V old = (V)mArray[index];mArray[index] = value;return old;}//不存在key ~index 就会返回key应该所在的位置index = ~index;if (osize >= mHashes.length) {final int n = osize >= (BASE_SIZE*2) ? (osize+(osize>>1)): (osize >= BASE_SIZE ? (BASE_SIZE*2) : BASE_SIZE);final int[] ohashes = mHashes;final Object[] oarray = mArray;allocArrays(n);if (mHashes.length > 0) {if (DEBUG) Log.d(TAG, "put: copy 0-" + osize + " to 0");System.arraycopy(ohashes, 0, mHashes, 0, ohashes.length);System.arraycopy(oarray, 0, mArray, 0, oarray.length);}freeArrays(ohashes, oarray, osize);}if (index < osize) {if (DEBUG) Log.d(TAG, "put: move " + index + "-" + (osize-index)+ " to " + (index+1));System.arraycopy(mHashes, index, mHashes, index + 1, osize - index);System.arraycopy(mArray, index << 1, mArray, (index + 1) << 1, (mSize - index) << 1);}mHashes[index] = hash;mArray[index<<1] = key;mArray[(index<<1)+1] = value;mSize++;return null;}int indexOf(Object key, int hash) {final int N = mSize;// Important fast case: if nothing is in here, nothing to look for.if (N == 0) {return ~0;}//二分查找Key的位置int index = binarySearchHashes(mHashes, N, hash);//<0  表示不存在  同时~index 会表示Key应该所在的位置// If the hash code wasn't found, then we have no entry for this key.if (index < 0) {return index;}//hasCode相同的情况呢? 会对key进行比较equals 直到找到对应的Key// If the key at the returned index matches, that's what we want.if (key.equals(mArray[index<<1])) {return index;}// Search for a matching key after the index.int end;for (end = index + 1; end < N && mHashes[end] == hash; end++) {if (key.equals(mArray[end << 1])) return end;}// Search for a matching key before the index.for (int i = index - 1; i >= 0 && mHashes[i] == hash; i--) {if (key.equals(mArray[i << 1])) return i;}// Key not found -- return negative value indicating where a// new entry for this key should go.  We use the end of the// hash chain to reduce the number of array entries that will// need to be copied when inserting.return ~end;}

Key对应的Hash 放入数组的时候,会进行排序
这样对于hasCode 就可以进行二分查找

get比较简单 直接返回mArray的value值即可

    public V get(Object key) {final int index = indexOfKey(key);return index >= 0 ? (V)mArray[(index<<1)+1] : null;}

删除
正常删除,当数组满足回收条件的时候 回收数组 下一次使用

    public V remove(Object key) {final int index = indexOfKey(key);if (index >= 0) {return removeAt(index);}return null;}public V removeAt(int index) {final Object old = mArray[(index << 1) + 1];final int osize = mSize;final int nsize;if (osize <= 1) {// Now empty.if (DEBUG) Log.d(TAG, "remove: shrink from " + mHashes.length + " to 0");final int[] ohashes = mHashes;final Object[] oarray = mArray;mHashes = EmptyArray.INT;mArray = EmptyArray.OBJECT;freeArrays(ohashes, oarray, osize);nsize = 0;} else {nsize = osize - 1;if (mHashes.length > (BASE_SIZE*2) && mSize < mHashes.length/3) {// Shrunk enough to reduce size of arrays.  We don't allow it to// shrink smaller than (BASE_SIZE*2) to avoid flapping between// that and BASE_SIZE.final int n = osize > (BASE_SIZE*2) ? (osize + (osize>>1)) : (BASE_SIZE*2);if (DEBUG) Log.d(TAG, "remove: shrink from " + mHashes.length + " to " + n);final int[] ohashes = mHashes;final Object[] oarray = mArray;allocArrays(n);if (index > 0) {if (DEBUG) Log.d(TAG, "remove: copy from 0-" + index + " to 0");System.arraycopy(ohashes, 0, mHashes, 0, index);System.arraycopy(oarray, 0, mArray, 0, index << 1);}if (index < nsize) {if (DEBUG) Log.d(TAG, "remove: copy from " + (index+1) + "-" + nsize+ " to " + index);System.arraycopy(ohashes, index + 1, mHashes, index, nsize - index);System.arraycopy(oarray, (index + 1) << 1, mArray, index << 1,(nsize - index) << 1);}} else {if (index < nsize) {if (DEBUG) Log.d(TAG, "remove: move " + (index+1) + "-" + nsize+ " to " + index);System.arraycopy(mHashes, index + 1, mHashes, index, nsize - index);System.arraycopy(mArray, (index + 1) << 1, mArray, index << 1,(nsize - index) << 1);}mArray[nsize << 1] = null;mArray[(nsize << 1) + 1] = null;}}if (CONCURRENT_MODIFICATION_EXCEPTIONS && osize != mSize) {throw new ConcurrentModificationException();}mSize = nsize;return (V)old;}

为什么省内存?

1.初始化内存较小
ArrayMap 默认为4 BASE_SIZE = 4
HashMap默认为16 static final int DEFAULT_INITIAL_CAPACITY = 1 << 4
2.增长策略不同
HashMap每次都是翻倍
newCap = oldCap << 1
ArrayMap 为:4 -> 8 -> 1.5倍

            final int n = osize >= (BASE_SIZE*2) ? (osize+(osize>>1)): (osize >= BASE_SIZE ? (BASE_SIZE*2) : BASE_SIZE);

3.ArrayMap 不需要创建Entry对象 因为全是数组保存的Key Value
4.ArrayMap使用了缓存池
当创建的数组不用的时候 会进行回收

 //长度为4的数组静态缓存池static Object[] mBaseCache;static int mBaseCacheSize;//长度为8的数组静态缓存池static Object[] mTwiceBaseCache;static int mTwiceBaseCacheSize;

Android ArrayMap源码解析相关推荐

  1. 不再害怕面试问ArrayMap一文完全看懂Android ArrayMap源码解析

    作者:VIjolie 前言 ArrayMap是谷歌推出的在安卓等设备上用于替代HashMap的数据结构,和HashMap相比,具有更高的内存使用率,因此适合在Android等内存较为紧张的移动设备,下 ...

  2. 【Android】Android Broadcast源码解析

    Android Broadcast源码解析 一.静态广播的注册 静态广播是通过PackageManagerService在启动的时候扫描已安装的应用去注册的. 在PackageManagerServi ...

  3. 【Android】Android Parcelable 源码解析

    Android Parcelable 源码解析 大家都知道,要想在Intent里面传递一些非基本类型的数据,有两种方式,一种实现Parcelable,另一种是实现Serializable接口.今天先不 ...

  4. Android Lifecycle源码解析(一)

    Android Lifecycle源码解析(一) 首先我们看HomeActivity中我们添加到一行代码 public class HomeActivity extends AppCompatActi ...

  5. Android xUtils3源码解析之图片模块

    本文已授权微信公众号<非著名程序员>原创首发,转载请务必注明出处. xUtils3源码解析系列 一. Android xUtils3源码解析之网络模块 二. Android xUtils3 ...

  6. Android xUtils3源码解析之注解模块

    本文已授权微信公众号<非著名程序员>原创首发,转载请务必注明出处. xUtils3源码解析系列 一. Android xUtils3源码解析之网络模块 二. Android xUtils3 ...

  7. Android xUtils3源码解析之数据库模块

    本文已授权微信公众号<非著名程序员>原创首发,转载请务必注明出处. xUtils3源码解析系列 一. Android xUtils3源码解析之网络模块 二. Android xUtils3 ...

  8. Android技术栈--HashMap和ArrayMap源码解析

    1 总览 WARNING!!:本文字数较多,内容较为完整并且部分内容难度较大,阅读本文需要较长时间,建议读者分段并耐心阅读. 本文会对 Android 中常用的数据结构进行源码解析,包括 HashMa ...

  9. Android技术栈(五)HashMap(包括红黑树)与ArrayMap源码解析

    1 总览 本文会对 Android 中常用HashMap(有红黑树)和ArrayMap进行源码解析,其中 HashMap 源码来自 Android Framework API 28 (JDK=1.8) ...

最新文章

  1. 查找谁在使用文件系统
  2. 鸿蒙开源小米能用吗,鸿蒙2.0开源,任何品牌都可以使用!小米用不用?
  3. Excel 2007 的重大bug
  4. 带有Swagger的Spring Rest API –集成和配置
  5. webstorm中vue项目--运行配制
  6. oracle命令行安装
  7. 高精度乘法(信息学奥赛一本通-T1307)
  8. PTA c语言 选择法排序过程
  9. java 计算两个日期之间的自然周
  10. Spring常用注解含义
  11. visio画图——圆柱
  12. sequel pro 格式化sql
  13. 无需重装系统,Windows Server 2019系统硬盘无损从MBR转换为GPT格式
  14. 【目标跟踪 MOT】JDE - Towards Real-Time Multi-Object Tracking
  15. “只用 1 分钟” - 超简极速 Apk 签名 多渠道打包神器
  16. 大白菜装机教程win10_如何通过U盘重装win10系统?
  17. 专访新致云田奎:行业云服务的差异化发展 初创公司上云迫在眉睫
  18. python 入门到实践期末考试常出现的考试内容_零基础Python入门及实践应用_章节测验,期末考试,慕课答案查询公众号...
  19. 前端笔试题及面试题(一)
  20. 深圳市社会组织信息平台爬虫获取信息

热门文章

  1. UML建模语言中的顺序图
  2. 我们唯一的选择其实就是向前
  3. python SQLite数据库操作
  4. mysql占用几个端口号_mysql占用端口号
  5. 很喜欢的句子,丧的时候就来看看吧
  6. 大数据借你一双慧眼 网络骗子地图上线
  7. js解决URL传递中文乱码
  8. algodoo 搭建二维物理引擎 写代码进行物理实验 让代码运行在可视的物理环境中
  9. Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springfr
  10. CentOS7查看开放端口命令、查看端口占用情况和开启端口命令、杀掉进程