ArrayMap源码解析
2016年6月5日
分析版本:support-v4-22.2.1
ArrayMap 继承于 SimpleArrayMap ,实现了 Map 接口中的所有方法。
ArrayMap
1 | public class ArrayMap<K, V> extends SimpleArrayMap<K, V> implements Map<K, V> { |
ArrayMap 中的具体实现方法是在 SimpleArrayMap 中实现的,而 ArrayMap 中实现 Map 接口的方法中,许多不建议使用,因为相比起 HashMap 等,效率要低的多。
SimpleArrayMap
1 | public class SimpleArrayMap<K, V> { |
put(K key, V value)
1 | public class SimpleArrayMap<K, V> { |
removeAt(int index)
1 | public class SimpleArrayMap<K, V> { |
remove 方法在特定情况下会进行内存重新分配,保证 ArrayMap 的内存合理区间,减少对内存的占用
其他 API
1 | public class SimpleArrayMap<K, V> { |
图说
ArrayMap 结构
查找
当要获取某个 value 的时候,ArrayMap 会计算输入 key 转换过后的 hash 值,然后对 hash 数组使用二分查找法寻找到对应的 index,然后我们可以通过这个 index 在另外一个数组中直接访问到需要的键值对。如果在第二个数组键值对中的 key 和前面输入的查询 key 不一致,那么就认为是发生了碰撞冲突。为了解决这个问题,会以该 key 为中心点,分别上下展开,逐个去对比查找,直到找到匹配的值。
删除插入
ArrayMap 的插入与删除的效率是不够高的,但是如果数组的列表只是在一百这个数量级上,则完全不用担心这些插入与删除的效率问题。
与 HashMap 内存占用对比
总结
- ArrayMap 根本不是哈希表,其实就是一个二叉查找树。有两个数组:key 的 hash 值数组,与对象数组的 key 索引对应,该数组用于二分查找;对象数组,存储真正的键值对,偶数索引是 key ,奇数索引是 value
- 为了快速扩展数组空间,使用了 static 的 array cache
- mBaseCache,如果 ArrayMap 的数据量从 4,增加到 8,用该数组保存之前使用的 mHashes 和 mArray ,这样如果数据量再变回 4 的时候,可以再次使用之前的数组,不需要再次申请空间,这样节省了一定的时间;
- ArrayMap 可以使用 index 遍历,会快一些
- ArrayMap 提供了数组收缩的功能,在 clear 或 remove 后,会重新收缩数组
最适合的使用场景
- 对象个数的数量级最好是千以内
- 数据组织形式包含 Map 结构