HashMap与SparseArray与ArrayMap

HashMap与SparseArray与ArrayMap

详细的 原文链接:https://blog.csdn.net/hq942845204/article/details/81293480

HashMap

HashMap内部存储结构是使用哈希表的拉链结构(数组+链表),Entry存储的内容有key、value、hash值、和next下一个Entry。


20200420182913791_346683073.png

这些Entry数据是按什么规则进行存储的呢?就是通过计算元素key的hash值,然后对HashMap中数组长度取余得到该元素存储的位置,计算公式为hash(key)%len。
那么如果取余得到的是相同的位置,就是产生了hash冲突,就会插入链表,在jdk1.8之前是插入头部的,在jdk1.8中是插入尾部的。
HashMap中的数据量>容量加载因子,(HashMap中默认的加载因子是0.75* )就会扩容,扩大后新的空间一定是原来的2倍,并重新计算素存储的位置

SparseArray

SparseArray比HashMap更省内存,在某些条件下性能更好,主要是因为它避免了对key的自动装箱(int转为Integer类型),它内部则是通过两个数组来进行数据存储的,一个存储key,另外一个存储value,为了优化性能,它内部对数据还采取了压缩的方式来表示稀疏数组的数据,从而节约内存空间,我们从源码中可以看到key和value分别是用数组表示:

        private int[] mKeys;
        private Object[] mValues;

SparseArray只能存储key为int类型的数据,不用装箱,性能好,每个元素的大小也小了,省内存。
SparseArray在存储和读取数据时候,使用的是二分查找法,所以,SparseArray存储的元素都是按元素的key值从小到大排列好的。
使用场景:数据量不大,key必须为int类型

SparseArray 优点:

通过它的三兄弟可以避免存取元素时的装箱和拆箱
频繁的插入删除操作效率高(延迟删除机制保证了效率)
会定期通过gc函数来清理内存,内存利用率高
放弃hash查找,使用二分查找,更轻量

SparseArray缺点:

二分查找的时间复杂度O(log n),大数据量的情况下,效率没有HashMap高
key只能是int 或者long

SparseArray应用场景:

item数量为 <1000级别的
存取的value为指定类型的,比如boolean、int、long,可以避免自动装箱和拆箱问题。

ArrayMap

20200429103225937_1562688667.png

存储结构,两个数组存储,一个存key的hash,一个存key和value ,添加元素时扩容机制,删除元素时的数组容量及时收缩。
hash数组也是按顺序排列的,利用二分查找在mhashes 数组中的index 下标值,找到对应mArray里面的key和value,index2是key的index,
index
2+1是value的index

ArrayMap优点:

在数据量少时,内存利用率高,及时的空间压缩机制

ArrayMap缺点:

存取复杂度高,花费大
二分查找的O(log n )时间复杂度远远小于HashMap
ArrayMap没有实现Serializable,不利于在Android中借助Bundle传输。

ArrayMap应用场景:

item数量为 <1000 级别的,尤其是在查询多,插入数据和删除数据不频繁的情况 

总结

(1) 首先二者都是适用于数据量小的情况,但是SparseArray以及他的三兄弟们避免了自动装箱和拆箱问题,也就是说在特定场景下,比如你存储的value值全部是int类型,并且key也是int类型,那么就采用SparseArray,其它情况就采用ArrayMap。
(2) 数据量多的时候当然还是使用HashMap啦

它们的出发点都是不变的就是以时间换空间

你可能感兴趣的:(HashMap与SparseArray与ArrayMap)