ArrayMap 和 HashMap 区别


1. HashMap

处理哈希冲突的方法:

2. ArrayMap

1、arrayMap的存储结构。

arrayMap中主要存储的数据的是两个数据,

int[] mHashes;
Object[] mArray;

mHashs中存储出的是每个key的hash值,并且在这些key的hash值在数组当中是从小到大排序的。

mArray的数组长度是mHashs的两倍,两个元素分别是key和value,这两元素对应mHashs中的hash值。mArray的结构如下图所示。

因为key的hash值是从小到大排列的,所以这里可以根据二分法来找对对应key的hash的位置index。

三、HashMap和ArrayMap各自的优势

1.查找效率

HashMap因为其根据hashcode的值直接算出index,所以其查找效率是随着数组长度增大而增加的。

ArrayMap使用的是二分法查找,所以当数组长度每增加一倍时,就需要多进行一次判断,效率下降。

所以对于Map数量比较大的情况下,推荐使用

2.扩容数量

HashMap初始值16个长度,每次扩容的时候,直接申请双倍的数组空间。

ArrayMap每次扩容的时候,如果size长度大于8时申请size*1.5个长度,大于4小于8时申请8个,小于4时申请4个。

这样比较ArrayMap其实是申请了更少的内存空间,但是扩容的频率会更高。因此,如果当数据量比较大的时候,还是使用HashMap更合适,因为其扩容的次数要比ArrayMap少很多。

3.扩容效率

HashMap每次扩容的时候时重新计算每个数组成员的位置,然后放到新的位置。

ArrayMap则是直接使用System.arraycopy。

所以效率上肯定是ArrayMap更占优势。

这里需要说明一下,网上有一种传闻说因为ArrayMap使用System.arraycopy更省内存空间,这一点我真的没有看出来。arraycopy也是把老的数组的对象一个一个的赋给新的数组。当然效率上肯定arraycopy更高,因为是直接调用的c层的代码。

4.内存耗费

以ArrayMap采用了一种独特的方式,能够重复的利用因为数据扩容而遗留下来的数组空间,方便下一个ArrayMap的使用。而HashMap没有这种设计。

由于ArrayMap只缓存了长度是4和8的时候,所以如果频繁的使用到Map,而且数据量都比较小的时候,ArrayMap无疑是相当的节省内存的。

5.总结

综上所述,

数据量比较小,并且需要频繁的使用Map存储数据的时候,推荐使用ArrayMap。

而数据量比较大的时候,则推荐使用HashMap。

补充

补充:HashMap 与 ArrayMap 的对比来自 Android SparseArray / ArrayMap 的实现(Java HashMap 是另一个生态概念)。两者核心区别:

  • HashMap(Java):基于 数组 + 链表 / 红黑树(JDK 8+ 桶内元素 ≥ 8 转红黑树),扩容时重新哈希,性能稳定但每个 entry 需额外存 key/value 的 Entry 对象 + 哈希码,内存占用大。
  • ArrayMap(Android):底层两个数组 mHashes(int[],保存 key 的 hash 升序排列)+ mArray(Object[],key 与 value 相邻存放)。查找时用 二分查找 定位 hash,内存紧凑(无额外 Entry 包装),适合几百量级的小 Map;数据量大时二分查找效率下降,扩容更频繁。

选择建议(Android 场景):

  • 容量 ≤ 几百:优先 ArrayMap,内存节省明显。
  • 容量大、查询密集:选 HashMap,O(1) 哈希查找更快。
  • 现代替代品:Kotlin mapOf 编译为 LinkedHashMap,兼顾顺序与性能;或者在 Android 中用 Protobuf / DataStore 序列化结构化数据。

来源整理自:我的有道云笔记