通过源码探查HashSet究竟是如何保证唯一性的
面试官: 你能简单介绍下List和Set有什么区别吗?
小憨: List是一个有序的集合,在内存是连续存储的,可以存储重复的元素,List查询快,增删慢; Set是一个无序的集合,在内存中不连续,不可以存储重复的元素,Set增删快,查询慢;
面试官: 那HashSet是如何保证元素不重复的?
小憨: 3分钟…
为了避免出现小憨这种知其然不知其所以然的尴尬,我们还是有必要来分析下上述问题的。
客官,且看下文
我们都知道HashSet存放的元素是不允许重复的,那么HashSet又是是如何保证元素不可重复的,你知道吗?
先看段源码 public class HashSet extends AbstractSet implements Set, Cloneable, java.io.Serializable { static final long serialVersionUID = -5024744406713321676L; private transient HashMap map; private static final Object PRESENT = new Object(); public HashSet() { map = new HashMap<>(); } public HashSet(Collection<? extends E> c) { map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16)); addAll(c); } public HashSet(int initialCapacity, float loadFactor) { map = new HashMap<>(initialCapacity, loadFactor); } }
乍一看这段代码,哎呦我去,new HashSet()操作不就不是维护了一个HashMap嘛,要是这么往下演的话,我觉得我这点功力也能看个大概呀!
诸位同仁,咱接着往下看 public boolean add(E e) { return map.put(e, PRESENT)==null; }
什么,这不就是map操作么,瞬间我来个下饭推理;
Map中的key是不允许重复的,而你HashSet正好利用我Map中key不重复的特性来校验重复元素,妙哉妙哉。
确实,HashSet确实是利用Map的这一特性实现了元素的不重复特性,但是我们再来深挖一下,Map他又是如何来保证key不重复的呢?
与其说这篇文章是介绍HashSet如何保证元素不重复的,倒不如说Map是如何保证Key不重复的。 final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) { Node[] tab; Node p; int n, i; if ((tab = table) == null || (n = tab.length) == 0) n = (tab = resize()).length; // 1、如果该位置不存在,直接插入 if ((p = tab[i = (n - 1) & hash]) == null) tab[i] = newNode(hash, key, value, null); else { Node e; K k; // 2、如果存在,判断是否是重复元素 if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) e = p; else if (p instanceof TreeNode) e = ((TreeNode)p).putTreeVal(this, tab, hash, key, value); else { for (int binCount = 0; ; ++binCount) { if ((e = p.next) == null) { p.next = newNode(hash, key, value, null); if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st treeifyBin(tab, hash); break; } if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) break; p = e; } } if (e != null) { // existing mapping for key V oldValue = e.value; if (!onlyIfAbsent || oldValue == null) e.value = value; afterNodeAccess(e); return oldValue; } } ++modCount; if (++size > threshold) resize(); afterNodeInsertion(evict); return null; }
上面部分我重点圈了两段代码,分别是1和2。
第一段 if ((p = tab[i = (n - 1) & hash]) == null)
这段代码其实主要是通过hash计算该元素的位置,然后判断该位置是否有值,如果没有值,那么可以直接插入,最后返回null;
第二段 if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) e = p;
如果通过计算,该位置上已经有其他元素,那么接下来就会通过hash和equals进行判断,判断它是不是重复元素,如果重复元素,那么最后会将这个重复元素返回。
通过第二段代码我们可以发现,判断元素是否重复,使用的是hash和equals方法进行判断的,所有我们Set里面如果存放的是对象,那么一定要重写hash和equals方法。
现在是不是很清晰了,为啥要重写equals方法了,不会出现那么诡异的代码了,这两个对象值都一样啊,为什么Set没去重呢!
每日一书怕怕不怕系列安全感绘本怕怕不怕系列安全感绘本(共6册),加梅兰妮瓦特著绘,喻之晓译,如果中信出版集团,2022年6月。适读年龄3这套书共6册,主角都是一个摆出同样表情的名叫怕怕的小松鼠。其中胆小的怕怕怕
三星GalaxyS23系列官宣2月2日发布,拍照亿点点提升IT之家1月11日消息,三星官宣将于北京时间2023年2月2日凌晨2点举行Galaxy新品发布会,预计就是新一代旗舰手机GalaxyS23系列了。三星官方发布了几段预热视频,可以看
马穆鲁克帝国时期,复杂多元的社会和现象,对女性有何影响?复杂的社会环境马穆鲁克本身的组成就是具有复杂性的特点,在这样的政权领导下,当时的埃及社会环境是由多民族之间共同建立的社会环境。从民族构成的角度来看,马穆鲁克人的种族复杂,移民现象更
认清楚什么是财富每次看到网络的视频人提起富有就说自己有几套房,几辆车,多少存款。我就为这个国家的很多普通人感到深深的悲哀!对什么是财富的概念这么地低级认识。存款不是财富,存款能买得到东西才是财富,
新能源领域就业热课题组成员清洗太阳能聚光镜。受访者供图进入冬季,新能源领域就业热度不减,新能源汽车光伏储能等行业的人才需求仍持续释放。某石油类高校2023届毕业生告诉中青报中青网记者,过去的校招季
爆满!深圳赴港签注预约近一周多数已满市民盼望早日恢复香港自助签南方财经全媒体记者欧雪深圳报道近日,受恢复通关和赴港旅游签注业务影响,深圳市出入境办证业务迎来高峰期。国家移民管理局公告表示,自1月8日起,有序恢复受理审批中国公民因出国旅游访友申
四季度盈利环比增长,盐湖股份全年预计盈利逾150亿元21世纪经济报道记者董鹏成都报道冬季受气温及天然气供给影响,盐湖产量会略有降低,不过盐湖股份去年四季度盈利仍然实现了环比增长。1月11日晚,盐湖股份发布全年业绩预告,当期预计实现净
美帝陷困境超贵科幻驱逐舰是废物,海上航空战力被大洋彼岸赶超据军事专家PY分析指出,金额庞大的2023年度美国国防预算草案通过之后,美国舆论竟然连篇累牍发表评论哭穷,说美国海军在驱逐舰作战能力海上航空战斗力方面极有可能几年内就被大洋彼岸的对
汇侨力献侨智海外华侨列席人大开幕会视频加载中在省十四届人大一次会议开幕会上,有8位来自欧洲中东东南亚南美洲等地的海外华侨受邀列席。他们当中,有些人祖籍就在四川,大家纷纷表示,参加开幕会,不仅让自己和人民代表大会制度
重庆与四川的区划变动,四川省的28个县,为何划入了重庆市?在之前的文章中,作者和大家聊了一系列关于我国四川省与周边各省区划变迁的故事,例如四川省与贵州省四川省与云南省之间的区划变迁。今天,我们聊聊四川省与重庆市之间的区划变迁。从50年代到
吃零食有幸福感,超三成用户年消费2000元以上追剧时吃零食聚会时吃零食下班时吃零食上班茶歇要吃零食出游也要吃零食在当代年轻人的日常生活中,吃零食已成为一种满足幸福感的方式。零食的消费场景亦细分为宿舍零食办公零食野餐零食养生零食
机关事业单位养老金和职业年金改革,2022年教师退休金的明显趋势大家好,欢迎关注我的养老和教育类专题,文章在交流中阅读,在交流中进步,在交流中思考,在交流中成长。教育行百业兴教师待遇,不断提高符合教育优先发展战略地位落实的要求,符合教师法和劳动
小升初简历,如何做才能让审核老师有看下去的冲动?学区房,是许多家庭都绕不开的话题,因为现在的中小学都是划片区入学。如果你的房子正处在某名校的招收范围内,也就是处在它的学区内,那你的孩子就可以直接入学了。但是,并不是所有的房子都在
万人迷陈好中戏讲课照流出,未施粉黛仍是佳人,尽显知性魅力随着网络时代的发展,越来越多的明星红极一时,让很多的学生也萌生了明星梦,选择走上艺考道路的学生也在逐年增加。今年的艺考基本已经结束,很多考生已经闯过了艺考的难关,距离自己心仪的院校
被裁员真的很可怕吗最近很多大厂被爆裁员,其实能够被爆出来,说明裁员并不是大部分公司出现的情况。比如说新闻上每天都会播报何时何地出现交通事故,让别人觉得车祸很多。但实际上并没有影响大众开车的热情。被裁
欢迎光临6集过后,开始高能,荒诞叙事,对抗现实冰冷5月21日,电视剧欢迎光临播出至第6集。我在对这部电视剧的首篇剧情文章当中说,这部电视剧是有人间烟火气的,有现实底色,出现的几位角色,能够让观众认为是真实的。6集剧情之后,我想补充
丰收中原满目新汝阳县蔡店镇一望无际的小麦长势喜人(5月18日摄)。谭勇段万卿摄河南日报报道组小满小满,麦粒渐满。5月21日,今年小满到。河南老乡们,麦熟了,快回来收麦吧,今年丰收了!微信朋友圈里
玻璃中间出现了水汽,我们该怎么办不知道大家有没有见过,家里的双层中空玻璃中间在温度变化的时候,有的时候会出现一层细细的水雾,厉害的时候甚至会凝结成为水珠形状,擦玻璃的时候也差不多,等到天气暖和的时候,这些水汽又会
昨晚大爆冷!昆仑决世界冠军被完爆,70KG杀出超级新星昨晚的ONE157比赛可谓爆冷连连,但最令人意外的一场比赛是羽量级踢拳对决中,前GLORY世界冠军昆仑决诸神之战冠军胡子杀手戴维特奇利亚竟然被一位新秀完爆落败。这位新秀名叫穆罕默德
马里乌波尔钢铁厂出土孙子兵法,很奇怪吗?自5月16日以来,随着亚速钢铁厂里的乌克兰武装人员陆续缴械投降,马里乌波尔最后的战斗已经结束,这座伤痕累累的城市正在恢复正常生活。5月17日,在一些瓦砾已经被清理干净的街区,路边摊
人这辈子,挣钱的目的到底是为了啥?人性商战会员密训人在什么时候最丢人呢?当你在最困难时候,出去借钱的时候,却什么也借不到的时候,那个时候最丢人,为啥说你去借钱,你的亲朋好友一个个都躲着你呢?一个个不是说刚好买了什么
微博自杀记昨天阅读了方慧的文章微博自杀记,女主人公和男朋友分手后,为了吸引男朋友对自己的关注进而到达破冰复合的目的,于是手段层出不穷的在微博上花式晒日常,然而每天毫无动静的微博让其很是心焦,