哈希表的实现

发布于:2023-01-18 ⋅ 阅读:(574) ⋅ 点赞:(0)

什么是哈希表:

                哈希表就是数组加链表

                或者是数组加红黑树

数组的特点:查询快,增删慢(根据索引值获取元素快)

链表的特点:查询慢,增删快

红黑树的特点:查询和增删都比较快

接下来我们来举例了解一个什么时候哈希表是数组加链表,什么时候哈希表是数组加红黑树。

.关于Set集合中我们知道,Set集合的特点是:没有索引值,元素不能重复。这里我们主要说一下关于Set集合下的HashSet集合,因为它的底层数据结构就是哈希表

1.我们先来创建一个HashSet集合

 这里新建了一个String类型的HashSet集合,在集合中添加了三个元素,我们打断点来看一下底层源码是怎么实现这个新增的。

2.进来后这里,我们实现的新增元素,所以这里的泛型e就是我们刚刚新增的zz,

3.再进来,这里的key就是zz,putVal方法中有五个参数,第一个参数是一个hash方法的返回值,我们再点进去看这个hash方法是怎么处理我们的zz的。

 4.这里有一个三元运算符,首先判断我们的zz是否为null,很明显,zz不为null,所以就返回(h = key.hashCode()) ^ (h >>> 16),这里的hashCode可以计算元素的地址值,仔细看这个方法返回的是一个int类型的值,获得这个值后赋给了h,然后将h右移了16位,与h再进行异或,然后将结果返回交给我们上一步中的hash(key)。(这里其实就是计算了哈希值)。

5.继续点进来,putVal中第一个参数就是我们刚刚计算出来的哈希值,第二个Value就是zz。

下面是一个Node类型的数组,对这个数组进行了一个if判断,判断一下这个数组是否有空间,为null就是没有空间,不为null就是有空间,没有空间就需要创建空间。这里我们的table为null就要进到resize方法。

 6.这里将table赋值给了oldTab,下面的判断oldTable为true,将0赋给oldCap,意思就是旧空间长度为0,下面的if就为false,就执行else部分。

 7.这里新的空间为16。(数组长度为16)

 8.这里就新建了一个Node类型的数组,长度为16,我们看一下这个Node是什么

 9.从右上角我们看见发现,Node是一个静态成员内部类。从下面成员变量Node<K,V> next;中可以知道,这是一个单项链表。最开始所说的哈希表是数组加链表,那么链表就是在这里体现的。

 10.这里n的值就是我们刚刚创建的数组长度16,数组创建好了,接下来就应该确定zz的索引值位置,那么zz的索引值位置是怎么确定的呢,我们接着往下运行。

 11.这里判断tab[i]的位置的值是否为null,等于null就是该位置没有元素,没有元素我们就可以将我们新增的元素新增进去,但是不为null就是该位置有元素,就不能直接新增元素。这个索引值i的值根据我们刚刚的数组长度n和之前计算出来的哈希值去确定的。

12.这里就是判断元素是否重复的规则。如果不重复就新增到该元素索引值的最后面,如果重复则不新增。


 二.这里我们再新建一个Integer类型的HashSet集合

 从图中我们可以知道,什么时候链表转为红黑树


 总结:

HashSet:无序:新增顺序和取出顺序不一定一致

  •       底层数据结构:哈希表(数组加链表/红黑树)
  •       什么类型的数组:java.util.HashMap$Node(表示一个单项链表)
  •       数组长度是多少:16
  •       如何判断新增的两个元素是否重复:
  •       规则:比较两个对象的哈希值&&(地址值相同||equals相同)
  •       新增过程:
  1.    a.计算新增元素的哈希值
  2.    b.(假设数组已经创建出来),通过hash%数组长度,获取索引值。
  3.    c.如果该位置为null:则直接新增
  4.    如果该位置不为null:
  5.     c1.判断该元素是否重复:
  6.    c11.如果不重复,则新增到该索引值位置链表的最后面
  7.     c12.如果重复:则不新增
  •       什么情况下链表会转红黑树:
  1. 当同一个索引值下元素个数>8,并且数组长度>=64会把"该索引值"下的元素转为红黑树。


网站公告

今日签到

点亮在社区的每一天
去签到