关于hashCode的疑问

zhangxianwei 2010-05-13 10:57:54
刚看了关于hashCode的一些文章,也大致了解了hashCode的功能,但是在看文章的时候,产生了一个疑问:

文章中把一个Set比做一堆桶,每个桶都有一个编号,这个编号就是hashCode。每个桶里面都装有元素。

那么把一个新的元素加入到set中时,需要获取元素的hashCode,通过hashCode查找桶,然后再对桶里面的元素分别用equals进行比较,如果没有相同的元素,则填入set。

问题是,如果上面的说法是正确的,那么如果有两个set,如set1和set2。当set1新增了一个元素test1后, set2再次增加test1时,也是通过test1的hashCode查询,这时就应该出现问题了啊,因为这个hashCode对应的地址已经有元素,并且equals也相同(因为都是test1)。可实际情况是set2也可以增加test1,说明没有问题。不理解中。。。
...全文
132 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
hackerster0324 2010-05-13
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 hackerster0324 的回复:]

set1是一堆桶,set2又是一堆桶。两个是独立的。。。这不就好理解了。
[/Quote]而且你说的是hashset如果是treeset就要看compareTo方法了。。
hackerster0324 2010-05-13
  • 打赏
  • 举报
回复
set1是一堆桶,set2又是一堆桶。两个是独立的。。。这不就好理解了。
lacus87 2010-05-13
  • 打赏
  • 举报
回复
LZ你这样想,
你定义了一个变量,只能引用一个对象,如果引用了其他对象原来的就没了
但是你定义了第二个变量,难道不能引用同一个对象吗
zhangxianwei 2010-05-13
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 soli11722984 的回复:]
还是理解不对,不过是另一个理解不对
set1指向是一个实例
set2又是指向另一个实例(set1和set2的hashcode基本不一致,就算一致,equals也不会一样)
set说的是在一个实例里,保存的元素不重复,既然是2个不同的实例,当然各有各的
[/Quote]

就如你说的,2个不同实例的情况是如何做的比较?
lacus87 2010-05-13
  • 打赏
  • 举报
回复
[Quote=引用楼主 zhangxianwei 的回复:]
因为这个hashCode对应的地址已经有元素,并且equals也相同(因为都是test1)。[/Quote]

set里面的对象都是引用,所以不存在一个引用了对象而另外一个不能引用的情况,
而且只有object中的hashcode值才和地址对应,
其他类中一般你都重写了hashcode。和对象的内存地址是无关
lacus87 2010-05-13
  • 打赏
  • 举报
回复
楼主你这个问题是因为你没有理解HASHSET的存储结构

其实HASHSET底层是用MAP去实现的,这个MAP的KEY对应每个对象的HASHCODE值,VALUE是一个链表

这样,每次放入HASHSET的时候,
1、判断HASHCODE,如果和其他的都不同直接放入SET中那个HASHCODE 为KEY所对应的链表
2、如果HASHCODE相等,判断EQUALS,如果相同,则判断两个对象相同,丢弃掉(就是放不进去)
3、如果HASHCODE相同,EQUALS不同,那么把这个对象放在这个HASHCODE为KEY锁对应的链表的最后一位
soli11722984 2010-05-13
  • 打赏
  • 举报
回复
还是理解不对,不过是另一个理解不对
set1指向是一个实例
set2又是指向另一个实例(set1和set2的hashcode基本不一致,就算一致,equals也不会一样)
set说的是在一个实例里,保存的元素不重复,既然是2个不同的实例,当然各有各的
shine333 2010-05-13
  • 打赏
  • 举报
回复
补充一下,
上面第二条是HashSet/Map等的工作机制,是基于第一条原理的。也就是说,存放、读取的时候,无需对所有已存在的元素进行比较
zhangxianwei 2010-05-13
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 soli11722984 的回复:]
因为set保存的不是一个实例,只是保存了一个hashcode,通过hashcode去查找对应的对象,所以set1和set2保存了test1的hashcode,而这个hashcode都是指向test1这个实例
[/Quote]


问题是set2要保存test1时,首先需要确认test1是不是重复元素。按文章中的做法是,首先获取test1的hashCode,再通过hashCode获取了链表,对链表做循环equals,如果相同则不加入,如果没有相同的则加入。
按照我的做法,set1在保存test1的时候,相当于这个hashCode对应的链表里面已经有这个对象了,那么set2再做保存的时候,同样是根据test1的hashCode做的查找,不就有重复元素了吗(因为set1添加test1的时候已经对这个hashCode做了操作)?
shine333 2010-05-13
  • 打赏
  • 举报
回复
理解错了,hashcode本身不是用来放东西的地址,而是用来
1:快速比较两个东西是不是一样。H一样,不一定相同,但H不一样,两者必不相同——除非你自己乱写hashCode方法
2:快速定位hashcode和存放的位置有一定的联系。add/set/put的时候,根据hashcode算出它应该在的位置,如果当前位置有人,判断是否相同(equals),相同则覆盖,不同,说明有冲撞,利用一定的算法解决。
soli11722984 2010-05-13
  • 打赏
  • 举报
回复
因为set保存的不是一个实例,只是保存了一个hashcode,通过hashcode去查找对应的对象,所以set1和set2保存了test1的hashcode,而这个hashcode都是指向test1这个实例

62,621

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧