当前位置: 首页 > 网络应用技术

Java Hashmap潜在的数据结构和方法实施原理

时间:2023-03-07 23:02:29 网络应用技术

  本文主要记录基于JDK 1.8的Java Hashmap基础数据结构,方法实施原理等。

  Java Hashmap的底层采用哈希表结构(数组+链接列表,JDK1.8是数组+链接列表或红色黑树),并结合了数组和链接列表的优点:

  Hashmap图标如下所示:

  Hashmap内部使用数组存储数据。数组中的每种元素类型是:

  节点包含四个字段:哈希,键,值,下一步,下一个指示链接列表的下一个节点。

  hashmap通过该方法计算哈希代码,然后通过公式在数组中获得键的竞标(n是数组的长度)。当存储在数组中的两个键一致时,数据将存储在链接的链接中方式(哈希冲突,哈希碰撞)。我们知道,在第一个元素中找到链接列表中的数据必须从第一个元素开始,才能找到一层和一层,直到找到它,时间复杂性为o(n),因此长度为链接列表中的越来越长。

  为了解决此问题,JDK1.8开始使用数组+链接列表的结构+红色和黑色树来实现hashmap。,链接列表将转换为红树和黑树。

  红树的节点由treenode表示:

  哈希图包含几个重要变量:

  分析源代码时,以上字段尤为重要。需要讨论的是负载因子是什么以及默认值为0.75F。

  例如,阵列容量为16,负载系数为0.75。然后,容量扩展阈值即,即数据数据的量大于12点钟,并且数组将被扩展。我们都知道,在创建阵列容量的大小时。SO称为扩展是指重新创建指定的数组,然后将旧值复制到新数组。扩展过程非常耗时,这将影响程序性能。因此,负载因子是容量和性能之间的平衡:

  可以看出,音量职业和绩效是对方之间的关系。他们的平衡点由负载因子确定。0.75是考虑能力和性能的经验价值。

  此外,用于存储数据的表字段使用瞬态修改。序列化时,通过瞬态修改的场将被排除。那么,HashMap在序列化序列化时如何恢复数据?HashMap通过自定义的ReadObject/writeObject方法自定义序列化和派生化。这主要是由于以下两个考虑因素:

  因此,在hashxxx类(例如Hashtable,Hashset,LinkedHashMap等)中,我们可以看到这些类是通过瞬态来修改的,以存储数据,并且所有这些类都自定义了ReadObject/writject.ReadObject/writeObject.dreadObject/writeObject方法。通过源代码进行分析。如果您有兴趣学习自己。

  PUT方法源代码如下:

  put方法通过哈希函数计算与键相对应的哈希值。哈希函数源代码如下:

  如果键为null并返回0,而不是null,则通过公式计算哈希值。此公式通过哈希码的高度16-位或低16位(主要是从性能和哈希碰撞的角度)获得哈希值,以减少系统开销,这不会导致碰撞,因为高水平不参与招标计算。

  获得与密钥相对应的哈希值后,然后调用该方法插入元素:

  放置操作过程摘要:

  与看台相比,这要简单得多。以下是获取操作源代码:

  根据以前的PUT源代码分析,我们知道该数组的初始化和扩展是通过调用调整大小的方法来完成的,因此现在请注意调整大小方法的源代码:

  JDK1.8是确定元素在容量扩展过程中是否需要通过高计算结果进行的。

  情况1:

  OldCap = 16扩展前,哈希= 5,,

  扩展后,newCap = 32,哈希= 5,。

  在这种情况下,扩展后元素索引的位置保持不变,哈希&oldcap == 0。

  情况2:

  OldCap = 16扩展前,哈希= 18,

  扩展后,newCap = 32,哈希= 18,

  在这种情况下,容量之后的元素索引位置为18,即旧索引2加16(OldCap)和Hash&OldCap!= 0。

  我们通常使用以下两种方法来遍历哈希图:

  程序输出:

  通过对上一侧的PUT源代码的分析,我们知道哈希图是无序的,输出元素的顺序和插入元素的顺序通常是不同的。但是您会多次找到上述过程每个遍历都是相同的。那么遍历的原理是什么,内部如何?

  通过入口集或钥匙集,它们的内部原理是相同的。这是一个示例。

  通过检查与代码相对应的类文件,您会发现以下代码实际上将转换为迭代器遍历:

  增强的循环将被编译为:

  让我们检查入口集的源代码,迭代器,hasnext,下一个方法,以清楚地理解哈希图遍历的原理:

  简而言之,遍历哈希图的过程是从头开始的哈希图数组中找到一个不道德的节点。如果节点下面有链接列表,则链接列表将被遍历。结果,继续进行直到遍历的结束。

  因此,如果一个红色和黑色的树结构在节点下,您如何遍历它?仍然可以通过红色和黑色树节点中的下一个字段找到下一个节点。

  JDK1.8 HashMap数组元素类型IS,JDK1.7 HashMap数组元素类型IS:

  实际上,这是一个班级名称,没有不同的本质。

  JDK1.7哈希计算规则是:

  与JDK1.8的哈希方法相比,JDK1.7的哈希方法的性能会更糟。

  JDK1.7不使用红色和黑树。与JDK1.8的尾部插入不同,JDK1.7采用了头部插入方法:

  JDK1.8确定元素是否需要在容量扩展时是否需要通过高级别的计算结果0。jdk1.7重新计算每个元素的哈希值。insert,在传输数据和容量扩展之后,链接列表易于: