Java的HashMap

1.基本概念:

它根据键的hashCode值存储数据,大多数情况下可以直接定位到它的值,因而具有很快的访问速度,遍历顺序不确定。最多允许一条记录的键为null,允许多条记录的值为null。非线程安全,若要满足线程安全,可以用Collection的synchronizedMap方法使HashMap具有线程安全的能力,或者使用ConcurrentHashMap。


2.底层实现:

数组+链表+红黑树(jdk1.8增加了红黑树)

(1)Node是HashMap的一个内部类,实现了Map.Entry接口,本质就是一个映射。

(2)HashMap采用链地址法解决hash冲突。

(3)Hash算法与扩容机制

Node[] table的初始化长度length(默认16),LoadFactor为负载因子(默认0.75),threshold是HashMap所能容纳的最大数据量的Node个数。threshold = length * LoadFactor。 数组长度确定后,负载因子越大,所能容纳的键值对个数越多。超过threshold这个值就要重新扩容。size指的是HashMap中实际存在的键值对数量。modCount记录HashMap内部结构发生变化的次数,主要用于迭代的快速失败,相同key的value被覆盖不属于结构变化。

为了避免出现拉链过长的情况,jdk1.8之后,对数据结构做了进一步优化,引入了红黑树,当链表长度太长(默认超过8)时,链表就转化为红黑树,利用红黑树快速增删改查的特点提高HashMap的性能。

hash算法:

三步:取key的hashCode值、高位运算、取模运算

对于任意给定的对象,只要它的hashCode()返回值相同,那么程序调用方法一所计算得到的Hash码值总是相同的。我们首先想到的就是把hash值对数组长度取模运算,这样一来,元素的分布相对来说是比较均匀的。但是,模运算的消耗还是比较大的,在HashMap中是这样做的:调用方法二来计算该对象应该保存在table数组的哪个索引处。

这个方法非常巧妙,它通过h & (table.length -1)来得到该对象的保存位,而HashMap底层数组的长度总是2的n次方,这是HashMap在速度上的优化。当length总是2的n次方时,h& (length-1)运算等价于对length取模,也就是h%length,但是&比%具有更高的效率。

在JDK1.8的实现中,优化了高位运算的算法,通过hashCode()的高16位异或低16位实现的:(h = k.hashCode()) ^ (h >>> 16),主要是从速度、功效、质量来考虑的,这么做可以在数组table的length比较小的时候,也能保证考虑到高低Bit都参与到Hash的计算中,同时不会有太大的开销。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值