今天学习集合最后一章节的时候,一道练习题让我对HashMap的底层结构的有了一个新的认知。
注:题目中的HashCode和equals方法会根据id和name来产生。
笔者第一次做错了,原因是认为在执行set.remove的时候,去除的就是HashMap指向的对象。
现在来讲解一下这个题目。
当添加了两个对象后,set的数据结构应该是这样(这里的hashcode是假设的):
当我们修改p1中name的值,那么就会在table节点为1的地方修改p1。请注意!这个时候没有使p1的存放位置发生改变,而仅仅是改变了数值。
随后我们执行了移出p1的操作。但!这个时候我们使用p1定位到的地址是new Person(1001,“CC”)这个对象所产生的HashCode(从题干中可知,这个对象的Hash产生方法已经被我们重写,所以HashCode会根据p1的数值发生变化)。
所以移除的操作是失败的!!!
此时输出的set有两个对象,一个是p1,一个是p2
随后,我们加入了一个新对象,这个新对象产生的hashCode和我们remove操作所定位的位置一样
,不会和之前的冲突,即使属性相同。这个时候的存储内容应该是这样:
所以此时输出的对象有三个p1,p2,new Person(1001,“CC”)
最后我们添加了一个和P1对象初始属性值一样的对象,所以产生的hashCode会和P1一开始一样。
HashSet底层存储需要看两个地方,一为HashCode,二为equals。通过题干可知,equals方法已经被Person类重写,根据属性来对比。所以新加入的这个对象虽然会定位地址和p1一样,但是会挂到p1节点后面,形成单项链表。
此时的结构应该是这样:
所以最终的结果会输出四个对象。