ArrayList 和LinkedList, HashMap 、SparseArray
ArrayList ---->逻辑上和物理内存都是连续的,方便查询,不方便插入删除(内部使用Systom.copy操作
LinkedList---->逻辑上连续但物理存储不连续,每个节点都有next,方便插入,不方便查询
HashMap --->结合了ArrayList 和LinkedList的优点, 内部使用hashcode作为table表的索引,
hashcode & (length-1),length-1 在内存上一定是1111 ....1111,取模时候每一位都用上了,节约内存空间
效率最高时候:链表中只有一个数据,链表有所有数据
hash碰撞的解决方案 :
1,链表法:将求模indexFor相同的index,放在同一个链表的头部,
2,0.75:空闲地址法,实践0.6-0.75之间使用效率高
3,扩容:达到hash 阈值(size * 0.75)就需要 扩容 x 2,浪费了内存 (假如16个坑位,hash值分布为2,11,就造成了内存大量浪费),一旦扩容,全部的数据需要重新hash,非常浪费时间,所以初始化时候都是(预设容量/0.75 + 1)
4,内存不可能一直扩容下去,就需要secondhash(),算法是google工程师为了让hash分布更为均匀的一个算法
5,红黑树:当链表长度大于8 && 链表长度大于64 时候,就将链表变成红黑树
6,初始化的时候,给table[]的长度是一个空的长度,当put进去元素的时候才去重新给size赋值
稀疏数组 SparseArray:两个长度相同的数组:mKeys,mValues,
- key只支持数字(可以避免hashMap自动拆箱装箱的过程,加快速度)
- 结构相对简单,只有两个数组,不需要其他结构(结构比较简单,不引入其他复杂结构)
频繁的插入删除SparseArray的速度会越来越快,原因是:
SparseArray虽然是离散数组,但是key的分布是:123...5...89一个自增的顺序,真正的提速关键在于:
当remove一个,并不是直接删除,而是将对应的mValues[index]--->赋值为一个new Object()空对象,这样就避免了System.arraycopy()操作,不用copy移动 index---length的元素,节约时间
当add一个,先二分法定位index,然后如果发现数组中存在一个new Obejct()的对象,就直接赋值这个对象,不存在再进行System.arrayCopy(),这样的有效的减少了copy时间,就加快了速率。
现实开发中,能用SparseArray就不用Hashmap,但是局限于SparseArray只能是int作为key,可以考虑将一些常量值写在xml中,使用R.String.xxx的方式引入,这样做只是增加了xml的大小,编译会慢一丢丢,但是可以大幅提升Runtime的执行效率。