黑马程序员技术交流社区

标题: <已解决>关于hashCode,为什么同一个哈希值位置上可存不同... [打印本页]

作者: 高原    时间: 2012-6-11 13:56
标题: <已解决>关于hashCode,为什么同一个哈希值位置上可存不同...
本帖最后由 高原 于 2012-6-12 09:13 编辑

HashSet保证元素的唯一性的原理是先判断hashcode,如果hashcode相同,而equals方法不同,那就再这个位置上再添加一个元素。
这里有几个问题想请教大家,
每一个对象都有自己的地址,哈希值是通过地址值算出来的,那为什么同一个哈希值上可以有不同的对象呢?
还有为什么要使用哈希值呢?为什么不直接使用地址值呢?
作者: 宋浩    时间: 2012-6-11 16:10
首先,HashSet的底层数据结构是哈希表。哈希表就是存储一系列哈希值的表,而哈希值是由对象的hashCode()方法生成的。
确保元素唯一性的两个方法,hashCode()和equals()方法。
当调用add()方法向集合中存入对象的时候,先比较此对象与原有对象的哈希值有没有一样的,如果都不一样就直接存入;如果有与之相同的哈希值,则要继续比较这两个对象是否为同一个对象,此时就要调用对象的equals()方法了。

总之,只有HashCode的至相同时,才会调用equals()方法。

在判断元素是否存在和删除一个元素的时候,也是这个过程。
作者: 黄奕豪    时间: 2012-6-11 16:38
首先毕老师教程视频中已经说了,如果相等就在原地址的位置顺延一个位置保存,这个位置据个人估计应该是链式的,因为当你看到张老师的基础加强视频以后你会明白,哈希表存储的底层数据结构是在内存中根据哈希表的值分成不同的段,这个是线式的,当有一个新元素进来时,会根据它的哈希值在内存中取哈希表分区的模,然后根据结果区域比较区域内的各个元素的哈希值,如果相等,就用毕老师在课上说的方法,在内存中顺延一个位置保存,但是这两个位置的哈希值都是一样的~~
作者: 郭宁    时间: 2012-6-11 23:10
依然想用最简单的阐述让你明白,所以避免不了一点差错,开兑:
话说咱有一个数数组  int[]  num = new int[100];
现在咱就像往里面存数据,但不允许重复。~~  你会怎么办? 每次存入数据的时候都 遍历一遍数组 检查重复不?   这就100个,不是个事,要我的数组是100000000长
效率可想而知。
咱们自己可以设计一个算法,咱起个名字就叫 hasNO()(没有,o(∩_∩)o 哈哈我的英语真的很湿)
这个算法干嘛用呢?~  就是 假如咱第一个存的是 101, 咱来个 index = 101%100=1  就是取101对100的余数,咱就把101存在num[1]中,下一次若再要存个101,一个取余数,直接就去与num[1] 比较,相等了就不存,不想等了就存,这样是否就提高效率了呢?
当然 咱要是存1  取余数  还是1 与num[1]比较后不想等,咱咋办呢?  咱可以在这个时候追加另一种算法~~~~~~~~~~

实际的hashcode  比这个要复杂的多了,你有兴趣可以研究一下。

通过上面的山寨方法 咱们可以得出一个概念:
相等的对象  必有相等的 hashcode
有相等hashcode 的两个对象 并不一定相等



好了,希望我的山寨方法 对楼主理解问题 有所帮助!
作者: 杨天皓    时间: 2012-6-12 00:02
HashSet集合里面,其实分成了若干个储存区域,每一个存进去的对象都可以计算出一个哈希值,然后可以将哈希值分组,每组分别对应某一个区域。所以当你存一个对象进去的时候,他会先算出hashCode,根据hashCode去找相对应的区域,然后在看有没有一样的hashCode,如果有一样。就不会往里面存。当然,你还可以重写equals方法,在hashcode值不同的情况下,去判断里面的值是否相等。

如果我说的你还不是很明白,请下载张老师的高新技术的视频。里面有一节是专门讲解hashCode和hashSetde
作者: 杨天皓    时间: 2012-6-12 00:05
顺便补充一个知识点吧:
如果你已经往HashSet里面传入了一个对象。

就不要对对这个对象经行修改操作了。

这样你只要一修改,这个hashCode的值就会随之改变。

那这样这个对象就没有办法去访问和调用了,它也会一直存在内存中不会释放。

这样就内存溢出了。
作者: 高原    时间: 2012-6-12 09:05
郭宁 发表于 2012-6-11 23:10
依然想用最简单的阐述让你明白,所以避免不了一点差错,开兑:
话说咱有一个数数组  int[]  num = new int[ ...

嗯,有点理解了,谢谢
作者: 高原    时间: 2012-6-12 09:08
杨天皓 发表于 2012-6-12 00:05
顺便补充一个知识点吧:
如果你已经往HashSet里面传入了一个对象。

多谢指教,我接下来就去看张老师的视频
作者: 高原    时间: 2012-6-12 09:15
黄奕豪 发表于 2012-6-11 16:38
首先毕老师教程视频中已经说了,如果相等就在原地址的位置顺延一个位置保存,这个位置据个人估计应该是链式 ...

谢谢,我会去看张老师的视频的




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2