HashSet类

 下面这个图就是当前table这个表的内容,有12个数组,这12个是有序的

我现在创建了两个节点。把第一个结点john放入table[2]中,接着我再把john的next指向另外一个新的结点jack,那么此时我的这个表是长这样的

现在上面就是数组加链表的方式存放的,

这就是一个HashMap

每一个数组元素都可以连接多个结点,在HashMat中红黑树的概念:当某个数组元素所在的那条链表挂载的结点达到8个时(包含第一个元素本身)产生一棵树,如果数组长度达到64的时候产生红黑树 。所以HashSet的存储方式是HashMap——数组+链表+红黑树

HashSet的扩容机制

简单来说下,我先说两个必须要先知道的,在Set接口类容器中他底层存放数据的方式是用数组加单链的形式存在的。我现在以以HashSet类为例子创建了一个Set接口类集合容器,在初始化的时候里面没数据的时候数组为大小0,这里先不说扩容机制,我往里面add1添加一个对象进去,他会先取得add1这个对象的哈希值,然后通过一个复杂的算法对哈希值进行转化,转化成一个简短的整数,因为哈希值这么长你不可能把哈希值当成一个数组的索引下标,所以需要转化成一个短的整数,这个转化后短的整数此时就作为索引下标而这个add1在数组中就对应该位置。注意这个转化的算法是统一的。好的,我暂且先把这个算法当做成   哈希值%13= 索引下标,当然这个算法就肯定不是这样的。接着比如    add1的哈希值%13 = 1,那么我就把第一个add1对象存入数组下标为1的位置,他不是直接就存进去的,他会做一系列的判断才决定add1是否能存进去,这里面因为add1是第一个元素所以他只做了一层判断,判断数组下标1中是否为null。接着我再存一个add2,add2的哈希值%13 = 6,      他直接找到下标6中的位置上,接着就是判断是否能够存入了,这里面跟add1一样只判断了一次就存入了。接着在我add3,add3的哈希值%13 = 1,   add3通过算法取得的值为1,这个时候他直接在数组中 找到下标为1的位置,第一次判断当前位置是否有元素,显然这里面有add1这个元素,接着他会调用下一层判断——equals判断,此时这个euqals判断就很灵活了你如果真的想传一个长的一样的对象进去那么不需要重写equals了,注意我说的是一样的而不是重复的。你new两个一样的对象进去不重写equals方法,就可以实现这样的需求了,因为你再放一个add3如果这个add3和add1一模一样长的,但是没有重写euqals方法他判断的就是你两是不是同一个对象,很明显这不是,那么不是同一个对象哈希值就不一样,这里面你可能会有疑惑到难道add1和add3的哈希值如果不一样的话通过这个统一的算法后会取得的值会一样???会的!!!就好比如我这个模除的算法来说加入add1的哈希值为1,add3的哈希值为14   这个1%13 == 14%13没毛病吧,你必须得明确你点他判断是否重复的依据euqals方法,但是这个equals方法是否判断值相等还是判断其他相等取决于程序员,回到正题,调用equals判断数值是否相等,那么我假设我调用equasl方法返回false,那么我我现在才把add3添加到数组下标为1的那个位置,此时它添加的方式就是用单链来实现了 ,在JdK8以前他是add3链接add1,在JDK8后他是用add1链接add3,简称七上八下。      接着我又添加了一个add4,add4哈希值经过算法转化后取得的下标是6,此时又开始判断6那里有没有元素,这里有add2,接着再equals方法,巧了你这个equals方法返回的是true,那么说明你两重复了所以add4加不进去。

HashSet的去重机制总结:他的去重机制取决于equals的返回值,比如你传入一个自定义类对象,在这个自定义类中没有重写euqals方法,那么你在添加元素的时候他判断你是否重复的的依据就是你两是不是同一个对象,比如:

​​​​​​​HashSet set = new HashSet();

set.add(new Person("yyy",18));

set.add(new Person("yyy",18));

如果Person类没有重写equals方法,那么equals判断的就是你两个new的对象是否是同一个对象,显然不是,所以他可以在比如索引为2的地方添加两个这样的Person类进去,这两个类形成一个链表。再比如你放两个int值1进去,那 equals判断int肯定就是判断值啊,所以肯定添加不进去。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

new麻油叶先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值