集合里的元素怎么“不见了”?( 二 )



运行结果如下:


$ javac Vertex.java$ java VertexfalseOptional[Vertex@2dd3e0]Optional[Vertex@2dd3e0]
明明和都一样,为什么就是false呢?
答案就在查找 Hash 表的方式 。我之前写过一篇文章《Hash碰撞和解决策略》,介绍如果发生 hash 碰撞,那么 hash 表一般会通过某种方式存放 hash 相同的元素 。这就要求,在 hash 表中查找元素的时候,必须满足以下两个条件,才算是找到了元素:
按照 hash 值能找到这个元素所在的 hash 位置,但是这个位置存放着很多 hash 值相同的元素,所以还要满足2;
必须满足相等() 。
Hash碰撞和解决策略:/posts/2493
其实就是没有 value 的,本质上也是个 hash 表,所以要返回 true,也必须满足上面两个条件 。元素在存进去的时候,name是空的,按照name是null得到了一个 hash 值,放到了的一个地方,记作位置 A 。然后我后来修改name的值,再 hash 的时候,就会得到另一个 hash 值,记作位置 B. 。然后去位置 B 一看,这个位置是个null,就认为这个元素不在集合中了 。

集合里的元素怎么“不见了”?

文章插图
为什么和返回都是相等的呢?因为我们先按照name = null保存了进去,保存的时候 hash 值已经确定了 。后来修改了name,hash 值已经不会修改(不会在里面移动的) 。虽然对象即使是同一个对象,但是 hash 值已经和放进去的时候变了 。拿现在的对象(Set里面的那个对象,和现在的要确定是否被的对象,都是“现在的对象”,name已经被修改了的)来对比 hash 值肯定是相等的,但是已经和放进去的时候的那个 hash 值不同了 。去看中,现在的这个 hash 值的位置,肯定是个null,所以判断为元素不存在 。
简单总结一下,就是放入 Hash 中的元素,一定要是不可修改的(这个和为什么 list 不能作为字典的 key?的原理是一样的) 。如果修改了,那这个元素就从集合中找不回来了 。
最后,从这个故事中我们能学到什么呢?
感觉学不到什么,现在回想起来就跟自己的智商受到了降维打击一样 。
哦,对了 。如果你看懂了这个问题,那么就会理解,之所以找不到这个元素是因为这个元素放进去的时候的和现在的这个元素的已经不一样了 。我不禁回忆起另外一个问题:
有三个人去住旅馆,住三间房,每一间房$10元,于是他们一共付给老板$30,第二天,老板觉得三间房只需要$25元就够了,于是叫小弟退回$5给三位客人 。
谁知小弟贪心,只退回每人$1,自己偷偷拿了$2,这样一来便等于那三位客人每人各花了九元,于是三个人一共花了$27,再加上小弟独吞了$2,总共是$29 。可是当初他们三个人一共付出$30那么还有$1呢?
欢迎在留言区留下你的观点,一起讨论提高 。如果今天的文章让你有新的启发,学习能力的提升上有新的认识,欢迎转发分享给更多人 。
欢迎各位读者加入订阅号程序员小乐技术群,在后台回复“加群”或者“学习”即可 。
猜你还想看
阿里、腾讯、百度、华为、京东最新面试题汇集
必须要掌握的异常处理
3.4k星,200余行代码,让你实时从视频中隐身
一次SQL查询优化原理分析(900W+数据,从17s到300ms)
关注订阅号「程序员小乐」,收看更多精彩内容
【集合里的元素怎么“不见了”?】嘿,你在看吗?