首页 > 编程知识 正文

HashMap和Hashtable的区别,hashmap底层实现原理红黑树

时间:2023-05-05 04:07:25 阅读:15485 作者:2512

在HashMap的底层实现中,采用了哈希表。 这是一个非常重要的数据结构。 对我们今后了解很多技术非常有帮助。 例如,redis数据库的核心技术与HashMap相同

数据结构通过数组和链表实现数据的存储,各有特点。

)1)排列:占用空间连续。 易于寻址,查询速度快。 但是,添加和删除效率非常低。

)2)链表)占用空间不连续。 寻址困难,查询速度慢。 但是,添加和删除非常有效率。

那么,是否可以将数组与链表的优点(即查询快,添加删除效率也高)结合起来? 答案是“哈希表”。 哈希表的本质是“数组链表”。

Hashmap基本结构的说明

哈希表的基本结构是“数组链表”。 打开HashMap源代码时,其中心内容如下:

其中的Node[] table是HashMap的核心数组结构,也称为“位桶数组”。 让我们看看什么是节点。 静态内部类Node

节点类存储:

1. key :关键对象

2 .值:值对象

3. next:以下节点

4 .混列:密钥对象的混列值

很明显,每个Node对象都是单向链表结构,以图形表示Node对象的典型图像。

HashMap的简单映像:

存储过程put (密钥,值)。

了解了HashMap的基本结构后,我继续深入学习HashMap如何存储数据。 其中的中心是生成用于与数组存储位置相对应的散列值的方法。

我们的目的是将“key-value个对象”存储在HashMap的Node[]数组中。 请参照以下步骤。

)1)获取密钥对象的hashcode

首先调用key对象的hashcode ()方法以获取hashcode。

)2)根据hashcode计算hash值([0,设为数组长度-1]的区间) ) ) )。

hashcode是整数,必须转换为[0,数组长度-1]的范围。 要求变换后的散列值尽量均等地分布在[0,数组长度-1]的区间,减少“散列冲突”

I .极端简单低的算法是:

散列值=hashcode/hashcode;

也就是说,混列值始终为1。 也就是说,键值和对象存储在数组索引1的位置,从而形成非常长的链表。 就像每次保存对象时都会发生“散列碰撞”一样,HashMap也退化为“链表”。

ii .一种简单而常用的算法是(相除剩馀算法) :

hash值=hashcode%数组长度

该算法可以将哈希值均匀分布在[0,数组长度-1]的区间内。 早期的HashTable采用了这种算法。 但是,这个算法使用了“除法”,所以效率很低。 JDK随后改进了算法。 首先,它保证数组的长度为2的整数幂。 由此,可以采用位运算来实现剩馀效果。 hash值=hashcode (数组长度-1)。

iii .采用JDK源代码的混列算法:

staticfinalinthash (对象密钥) {

int h;

返回(key==null )? 0:(h=key.hashcode () ) ) ) ) ) ) ) );

}

)3)生成节点对象

如上所述,一个Node对象包含四个部分: key对象、value对象、hash值和对以下Node对象的引用: 我们现在计算出了hash值。 对以下节点对象的引用为null :

)4)将Node对象放入table数组中

如果节点对象未位于与此节点对象相对应的数组索引位置,请将节点对象直接存储在数组中。 如果相应的索引位置已经有节点对象,则现有节点对象的next将指向此节点对象,从而形成链表。

总结以上流程。

添加元素" key-value "时,首先计算key的散列值以确定其在数组中的插入位置,但具有相同散列值的元素可能已经位于数组中的同一位置。 在这种情况下,它将添加到具有相同散列值的元素之后,并在数组的相同位置形成链表。 同一链表上的混列值相同,这意味着数组在JDK8中,如果链表长度超过8,链表将转换为红黑树,大大提高了搜索效率。

获取数据进程get(key )

必须从key对象中检索“键-值对”对象,然后返回到value对象。 了解存储数据的过程后,获取数据很容易。 请参阅以下步骤。

)1)获取key的hashcode,hash ) )通过散列算法获取hash值,并定位到数组位置。

)2)在链表中逐一比较key对象。 调用equals ()方法,将key对象与链表中所有节点的key对象进行比较,直到遇到返回true的节点对象。

)3) equals ) )返回true的节点对象的value对象。

知道了访问数据的过程。 让我们看看hashcode () )和equals方法之间的关系。

Java规定,两个内容相同且equals ()为true的对象必须具有相同的hashCode。 equals ) )为true,如果两个对象的hashcode不同,则在保存过程中出现了悖论。

扩张问题

混叠映射的位桶数组。 初始尺寸是16。 实际使用时,很明显大小是可变的。 位桶数组的元素达到(0.75*数组长度)后,将数组大小调整为两倍。

扩展需要时间。 扩展的本质是定义新的更大数组,然后将旧数组的内容一个接一个地复制到新数组中。

JDK8在链表大于8的情况下变为红黑二叉树

在JDK8中,HashMap存储单个元素时,如果相应的链表长度大于8,则链表将转换为红黑树,从而大大提高了搜索效率。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。