Map的三个特色html
1.包含键值对
2.键惟一
3.键对应的值惟一算法
Hash,也能够称为“散列”,就是把任意长度的输入,经过散列算法,变换成固定长度的输出,该输出就是散列值。这是一种压缩映射,也就是,散列值的空间一般远小于输入的空间,不一样的输入可能会散列成相同的输出(也就是多对一的关系)。数组
HashMap内部是使用一个默认容量为16的数组来存储数据的,而数组中每个元素却又是一个链表的头结点,因此,更准确的来讲,HashMap内部存储结构是使用哈希表的拉链结构(数组+链表),这种存储数据的方法叫作拉链法 。如图: 数据结构
且每个结点都是Entry类型,那么Entry是什么呢?咱们来看看HashMap中Entry的属性:性能
1 final K key; 2 final V value; 3 final int hash; 4 HashMapEntry<K, V> next;
从中咱们得知Entry存储的内容有key、value、hash值、和next下一个Entry,那么,这些Entry数据是按什么规则进行存储的呢?就是经过计算元素key的hash值,而后对HashMap中数组长度取余获得该元素存储的位置,计算公式为hash(key)%len,好比:假设hash(14)=14,hash(30)=30,hash(46)=46 咱们对len取余,获得hash(14)%16=14,hash(30)%16=14,hash(46)%16=14。因此hash值为14的这个元素存储在数组下标为14的位置。优化
从中能够看出,若是有多个元素key的hash值相同的话,后一个元素并不会覆盖上一个元素,而是采起链表的方式,把以后加进来的元素加入链表末尾,从而解决了hash冲突的问题,由此咱们知道HashMap中处理hash冲突的方法是链地址法。spa
在此补充一个知识点,处理hash冲突的方法有如下几种:设计
讲到这里,重点来了,咱们知道HashMap中默认的存储大小就是一个容量为16的数组,因此当咱们建立出一个HashMap对象时,即便里面没有任何元素,也要分别一块内存空间给它,并且,咱们再不断的向HashMap里put数据时,当达到必定的容量限制时(这个容量知足这样的一个关系时候将会扩容:HashMap中的数据量>容量*加载因子,而HashMap中默认的加载因子是0.75),HashMap的空间将会扩大,并且扩大后新的空间必定是原来的2倍,咱们能够看put()方法中有这样的一行代码:3d
1 int newCapacity = oldCapacity * 2;
因此,只要一知足扩容条件,HashMap的空间将会以2倍的规律进行增大。假如咱们有几十万、几百万条数据,那么HashMap要存储完这些数据将要不断的扩容,并且在此过程当中也须要不断的作hash运算,这将对咱们的内存空间形成很大消耗和浪费,并且HashMap获取数据是经过遍历Entry[]数组来获得对应的元素,在数据量很大时候会比较慢,因此在Android中,HashMap是比较费内存的。code
因此咱们在一些状况下可使用SparseArray和ArrayMap来代替HashMap。
ArrayMap是一个<key,value>映射的数据结构,它设计上更多的是考虑内存的优化,内部是使用两个数组进行数据存储,一个数组记录key的hash值,另一个数组记录Value值,它和SparseArray同样,也会对key使用二分法进行从小到大排序,在添加、删除、查找数据的时候都是先使用二分查找法获得相应的index,而后经过index来进行添加、查找、删除等操做,因此,应用场景和SparseArray的同样,若是在数据量比较大的状况下,那么它的性能将退化至少50%。
ArrayMap方法:
public V put(K key, V value) public V get(Objectkey) public V remove(Objectkey) public K keyAt(int index) public V valueAt(int index)
ArrayMap应用场景
欢迎你们关注公众号,不定时干货,只作有价值的输出
做者:Dawnzhang
出处:https://www.cnblogs.com/clwydjgs/版权:本文版权归做者转载:欢迎转载,但未经做者赞成,必须保留此段声明;必须在文章中给出原文链接;不然必究法律责任