根据面试经验,浅谈hashmap底层实现

来源:互联网 发布:音频美化软件 编辑:程序博客网 时间:2024/05/01 21:51

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).开放定址法

- - - - - - - - -关于这三种方法,在后期的文章中会逐步讲解

经过参加了几个面试,总结了一下经常问到的问题,hashmap底层实现是最经常遇到的问题之一,所以今天在这里,浅谈一下自己的见解,如有错误,希望可以指出,本人感激不尽,都是为了提高水平,增长知识嘛!谢谢。。

   
原创粉丝点击