集合框架3:快速查找之“哈希集合”

来源:互联网 发布:朝核危机 知乎 编辑:程序博客网 时间:2024/06/06 00:03

hash是集合中查找速度最快的,数据量越大查找的优势与其他集合就越明显。那怎么做的呢?这里将讲解一个盗版的哈希集合,何为盗版,和系统的哈希有区别,后面讲解。


如何添加数据


哈希集合的添加和其他集合略有区别,在添加的时候多了一点步骤,为什么哈希查找速度块?因为在添加数据的时候做了准备,后面讲解。所以哈希添加速度不快,查找速度快。


首先先询问,添加的是数据obj是否为null,为null报错,不添加空数据,不为空就计算出此对象的hash(hashCode)值,hash值也是存在负数的,询问是否小于0,来判断负数取反~


计算好hash值后,拿着数组计算的这个下标询问是否为null?为什么呢?看下图


这是咋们hash存储方法,旁边的数组就是数组长度,右边的值是需要添加的数据,先计算a的hash值,取余放在数组的下标中,假设a的hashCode的是123,取余后的值是1,就放在数组的第一个值中,


b的hashCode值是456,取余后的值是4,就放在数组的第4个下标上,到了c,c的hashCode值计算也为123,取余等于1,此刻,下标为1存了值了,怎么办呢?挂在a下面吧。


怎么挂?不能覆盖选择类似链表的形式引用挂在a下面即可,和系统哈希集合的区别正是在这里,咋们是碰到计算出重复的值可以挂在下面,而系统计算出重复的哈希值取余后,不挂在此下标下面,


系统是给每一个值都一个坐标,我们是选择挂在重复的下标,查找的时候,系统因为下标的唯一不考虑重复的下标,故而查找速度更快。但系统的添加就又稍慢一些,有舍有得。


回到之前的问题,取余后得到重复的值怎么办?我们这里采用单链的形式去做,才能不覆盖以前的值,凭借引用关系,把重复的取余值挂在下面。


这里采用单链,还有系统的集合不能添加重复值,我用debug看了一下,系统集合是添加重复值id还是一样,说明并没有添加进入,只有值不一样,计算的结果不一样,才会添加到HashaSet中


我们这里是可以添加重复值的,主要是为了方便,就不写了,猜测系统的哈希集合如果添加重复值的话,在查找上面,首先系统集合就没有添加重复值一说。


因为每一个值都是拥有独立的下标,重复的就是引用关系,就没给重复的独立下标了。所以,如果系统集合可以添加重复值。对于重复值查找这一块比较麻烦。


回到之前,采用单链来把重复值挂在下面,第一个没有值的时候,申请3个长度的数组,第一个空间存值,第二个空间是存储下家的,第一次没有下一家不管,第三个空间存储尾巴,第一次只有自己做为尾巴了。


第二次,计算到重复值了,申请数组,单链继头之后就是2个长度,第一个空间存储值,第二个空间存储下家,头的最后一个空间来不停引用新加的数据数组做为尾巴。


第一次时,new出为三的数组,尾巴引用自己,第二次下标上有人了,拿出这个数组,尾巴引用这个拿出数组的第二个空间,也就是尾巴,第二次拿的这个尾巴还是自己这个头。


新建数组,长度为2,第一个存数据,第二个为null,是下家,现在没有下家,尾巴的第一个,也就是头的第一个也就上引用下家的这个一个引用这个新建数组,这个数组的第二个引用新建数组,做为引用的尾巴。


第三次,取出头这个数组,尾巴拿到头的尾巴,第三次拿到的也就是刚刚尾巴转变引用的第二个数组,根据这个转变引用的尾巴,不停的拿到最后一个数组数据。


拿到后,变量名尾巴引用,新建数组,第一个数据第二个为null,尾巴的第一个,就不再是头与第二个转换了,而是后面与后面的引用转换,尾巴刚刚拿到的最后一个数组数据。


尾巴拿到后,也就上最后数组数据,尾巴的第一个,也就上数组长度为2的第第二个空间第一个下标,引用下家的这个引用着新建数组,也就是最后一个数组数据引用这个新的数组数据。


objs【2】也就上头的第二个,也就上真正引用尾巴的数据改变引用,改变引用,在下一次,也是取出头,引用头之前引用的最后一个尾巴,拿着最后一个数组数据改变引用,拿着头的尾巴改变引用。单链就这样形成了。


咋们的哈希集合重复值就是这样做的,咋们的碰到重复的就挂在下面,即使是碰取余相同,也是新建数组,所以地址依然不一样,而系统的集合,碰到相同的id也是一样,也就上不改变,不挂值,重复的就重复。


系统集合更快是因为不担心下标相同的问题,定位就更加方便了,我们检索定位需要考虑重复的,往下寻找到相同的。


查找方法


查找方法是传入对象,查询是否有,返回布尔。先询问查询的值是是否为null,为空就报错。不为空,计算hashCode,取余后的结果,为负数取反即可,while询问,为社么?因为你不知道此下标挂了多少值,


先拿到这个值,询问这个是否为null,为null还没有数据,没有数据查询肯定就没有结果,返回false,如果下面有值,就可以继续进行查找,拿出第一个空间,第0个存储数据的下标用equals比较是否相等,


相等代表一样的数据,找到了返回true,如果没有找到,取出自身的第2个空间,第一个下标也就是下家的值,继续equals比较,最后询问到最后也是个空指针报错,查询方法完成。


为什么哈希集合查找厉害,因为在添加值的时候计算好一个值,进行存储,查找的时候拿着这个计算好的值,直接去那个下标进行询问查找即可,而如果是LinkList,ArrayList集合就只有一个个从前置后,从上至下,一个个询问是否相等,多慢。


hash集合,直接就定到位置,比较是否相等即可,而系统集合直接就定到位置找到了,不用管重复下标值下面挂的值嘛。本期完;

原创粉丝点击