关于HashMap的数据存储结构,以及冲突问题的解决原理

42 篇文章 0 订阅
16 篇文章 0 订阅

首先我们都知道hashmap是用的数组+链表的数据结构来存储数据的,存入的数据也是通过键值对key/value这样的方式,下面整理的是比较底层的一些源码分析:

1. 首先我们要知道什么是 hash 函数:

hash函数就是将一个任意长度的二进制值,通过映射关系也就是hashmap底层用到的一个hash算法,转化成固定长度的二进制值,得到一个hash值

2. HashMap的实现原理:

hashmap存储的数据结构:数组+链表+二叉树(黑红树)
hashmap存值: hashmap查找速度快效率高的原因是因为,存值的时候就是根据 key 通过 hash() 算法计算出 hash 值,然后再把这个 hash 值对数组长度取余数(%)来计算出存储位置,数组长度默认是16位,存储东西多的时候可以扩充数组长度
hashmap取值: 取值的时候也一样,给到你要去的 值的key 键,hash算法可以直接计算出这个key的储存位置就可以取到相应的值了,不需要去遍历查找
链表的形成: 当有多个参数但是hash值是一样的时候,数组中同一个位置存储了多个key 对象时就会形成链表,在版本1.8之后,如果链表长度大于等于8的时候就会转换成二叉树的形式来存储数据,链表将转换成红黑数结构存储,红黑数的结构可以使链表两边的长度均等,这样的目的是为了取值更快,存储的数据量越大的时候,性能表现的越明显

3. HashMap的冲突问题解决方式:

当有多个参数但是hash值是一样的时候,代表多个参数的 key 指向的存储位置发生了冲突,有两个方法可以处理这样的冲突问题
方法一:线性探测法, 探测步长是1,就是在数组中先将参数 key1 放在对应的位置,然后 将 key2 继续往后探测,如果遇到空的位置就把 key2 添加在这个位置上
方法二:链表形式, 遇到冲突的key的时候会把之前的元素覆盖掉,然后指向原来的元素,新的元素始终是在数组头位置,取值的时候用迭代的方式来取

4. hashmap存储过程中的几个重要关键词解释:

1.hash表:数组+链表+二叉树(红黑树)
2.加载因子:数组的扩容,默认值为0.75,意思是这个数组空间储存的动词超过百分之七十五就到了上线,需要重新扩充也就是散裂,数组的默认长度是16,这个在hashmap 源码的构造函数中可以更改
3.把参数储存到hash表中如何存储?
比如 key 的hash 值是 1434,它在数组中的位置就是 1434%16 计算出的结果,值也就放在了这个对应的位置

5. hashmap和hashtable的区别:

1.hashmap是可以把null做为键或值,hashtable不可以
2.hashmap是线程不安全的,但是效率比较高,hashtable线程安全但是效率低
3.如果想要线程安全效率又高,可以使用concurrentHasnmap,把一个map分成多个map这样就实现了线程安全

6. hashCode() 和 equals() 的重要性的体现:
  • Java中的hashMap使用 hashCode() 和 equals() 方法来确定键值对的索引,当根据键获取值得时候也会用到这两个方法,如果没有正确的实现这两个方法,两个不同的键可能会有相同的hash值,因此,肯呢个会被集合认为是相等的,而且这两个方法也用来发现重复元素,所以这两个方法的实现对hashMap的精确性和正确性谁至关重要的
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值