白话讲hashMap

   学了几天hashmap,收获很大。但是我想用自己的大白话说一边。各位看官仔细看,有不对还请提出。感激不尽!

如果你能找到本文的疏漏之处,说明你对hashmap有了更深的理解;



说起hashMap的时候。必须提一下hashtable,因为hashmap是hashtable的轻量级实现,他继承了hashtable除了多线程方面的几乎所有的内容,并且hashmap在单线程的效率比hashTable高一点,原因是hashmap不需要进行同步锁的维护,数据更新也不需要去检测;另外hashmap可以接受null作为键和值,这估计是他的设计者认为null在逻辑中也是可以有意义的;另外,hashmap实现的是map接口,而hashtable是基于陈旧的dictionary类;

       当然了,hashmap在线程安全上比不上hashtable,如果你想在多线程中使用hashmap,必须要自己加入同步方法;然而jdk提供一个叫做ConcurrentHashMap的类,相比于hashtable中所有的线程去竞争同一把锁,它在多线程中使用多段锁,每一段锁保护一个fragment,大大缓解了高并发中线程竞争,从而提高了效率。

       hashtable已经是一个过时类了,现在很少在代码中见到了。

 

       接下来说一说hashmap的数据结构。hashmap在查询时候的时间复杂度是O(1),原因是他像我们使用数组时一样,直接通过下标去找要得到的值,这一定比挨个查找的O(n)快的多得多;

       hashmap在细节上是通过将key对应的对象进行hashcode(),得到的这个值同模map长度后得到了key所对应的value在JVM的地址,直接从地址中取数据就可以了;

       接下来讲一下hashcode()散列函数,刚才说到讲key对象转化为32位整形,很显然这带来了一个问题:碰撞冲突问题:如果2个不同的对象得到的hash值是一样的,怎么处理呢?

       处理碰撞冲突的办法有很多,在这里Java采用的数组+链表的结构。

       (最简单的是开放地址,线性探测法,但是它不能删除元素,只能添加删除标志;其实是再hash法,他是重新算一遍hash值,我感觉这种方法也会带来一些问题;还有就是建立一个公共溢出的地方,这个方法有点太粗暴了,我觉得他也只是暂时解决了冲突问题,如果在溢出区溢出很多呢?所以这几种不完美的解决冲突方案没有被采用,只是留作历史,让后来的人学习他的解决问题的思想)

       当冲突发生后,Java会将加进来的value放在索引对应的地址后面的第一个位置,之前的第一个元素成为了第二个;查询的时候只需要在数组后面的链表中遍历一次就好了,这种思想当时确实解决了很多问题,当然他也带来了一个问题;Java中字符串的散列函数是很简单,他的乘法基数是31,对于这个很小的素数,有心人能够很容易的得到大量hash值相等的字符串,恶意地插入你的map中,你以为你的hashmap的复杂度是O(1),其实已经近似成了O(n).所以呢Java最新的1.8做了优化,当散链的长度大于8的时候,把散链重构成一颗红黑树,解决了上面的问题;当然他的代价是重构和维护红黑树的开销咯;

       当然,hashmap中的第一难题是冲突解决,那第二难题就是扩容了。当hashmap的元素数目越来越接近的其最大容量时,不可避免,大量的冲突产生,大量的散链也产生了,查询的代价大大提高,这时候就有一个问题,什么标志作为拥挤的信号呢?Java中有一个加载因子,0.75,当元素数量大于最大容量*加载因子的时候进行扩容。hashmap的初始最大容量时16,以后每次扩容都乘2。这样做的好处是可以减少在长度变化后元素位置重新确定的代价。jdk1.8最新的优化:如果最大容量扩容前是2的N次方,那么去看元素hash的倒数第N+1位上是0还是1,如果是0,位置不需要调整,是1,就把索引的值+扩容前的最大容量,也样做的好处就是大概有一半的元素不需要移动,扩容的代价有一定的减少。

 

 

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值