1.hashmap最常用的实现方法:拉链法 可以理解为:数组+链表
数组:存储区间是连续的,占用内存严重,所以空间复杂度大,但是在二分查找的时候,时间复杂度小,不灵活特点:寻址容易,但是插入和删除困难,因为插入的时候,后面数据的会依次向后移动
链表:存储区间是离散的,占用内存不叫宽松,所以空间复杂度小,但是时间复杂度大
特点:寻址困难,但是插入,删除容易
哈希表:综合了这两者的特性,即数组+链表,数组长度为16,每个元素存储的是一个链表的头结点
通过key的hashcode值,然后int index=(hashcode值)%(数组的length),index就是数组的下标,
通过index下标找到相应的数组
这个线性数组实现按键值对的方式存储数据:
这里用到的就是hashmap中的entry数组,其中属性有key,value,和next,
这里entry就是hashmap键值对实现的基础bean。map里面的内容都存在entry[]数组里面。
2.hashmap的存取:
1)首先,存的时候:
代码:
int index=key.hashcode()%entry[].length;
entry[index]=value;这里需要说一下当得到的index重复时的解决方法:
这里就用到了entry的next属性啦。ok,继续!
如果有键值对a,通过计算,a的key的index=0,这时候在entry数组里就会entry[0]=a;
如果后面进来的键值对b,他的key的index也等于0,那么就会:b.next=a;entry[0]=b; 链表存储嘛。
后面如果key的index再相同,就以此类推。
敲黑板,划重点:数组中存储的是最后插入的元素!!!!!!
随着map的size越来越大,entry的长度就会按照一定规则扩充(这个规则会在后面讲解)
这里会涉及到一个因子:一般设置为0.75(一般认为最优),意思是将分配的内存的25%作为缓冲,来更加高效的实现数据的存取
2)然后,取的时候:
代码:
int index=key.hashcode()%entry[].length;
return entry[index];这里用数组的下标确定目标元素在数组中的位置,效率较高
3)关于null key的存取
null key 总是放在entry数组的第一个位置3.关于解决hash冲突的方法
1).链地址法(hashmap的解决就是采用的这用方法)2).再哈希法
3).开放定址法
- - - - - - - - -关于这三种方法,在后期的文章中会逐步讲解