A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 贾文泽 高级黑马   /  2013-1-21 16:50  /  3130 人查看  /  15 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 IC-月辰 于 2013-1-22 10:18 编辑

对象的相等性比较——euqals()
当直接传入对象进行比较时,比较的是两个对象的内存地址的哈希值,
在Object提供的hashCode()方法的默认实现是通过将对象的内存地址转换成一个整数值来生成。

那么,试考虑,有没有这样的情况存在。两个不同的对象会有相同的哈希值?

最终解释:
木有人考虑到两个不同的变量的哈希值会相同么?
其实我想说,这种情况是存在的。用老毕的话说,你们肯定会认为是我疯了,但是...

每个对象都有自己的哈希码,利用这个哈希码可以表示一个对象,在Object提供的hashCode()方法的默认实现是通过将对象的内存地址转换为一个整数值来生成。由于在某些架构上,地址空间大于int值的范围,两个不同的对象有相同的hashCode()是可能的...

评分

参与人数 1技术分 +1 收起 理由
Rancho_Gump + 1 神马都是浮云

查看全部评分

15 个回复

倒序浏览
复写hashcode( )方法就有了
回复 使用道具 举报
左兆彬 发表于 2013-1-21 17:00
复写hashcode( )方法就有了

问题是不复写hashCode()方法的,也就是说,有没有可能出现这种情况,不一样的两个对象的默认hashCode值是一样的。。。。?
回复 使用道具 举报
应该不可能吧,不覆写hashCode()方法,对象继承的是Object的hashCode()方法,该方法是根据对象的地址值通过特定的算法计算出来的,不可能两个对象占着同一个地址值吧
这样新来的对象不就把原来的对象覆盖掉了吗,一个房子不可能同时有两户人家居住吧
下面是我的HashSet笔记,你看一下吧,也不知道对不对
  1. /*
  2. *用于测试HashSet容器是怎么判断重复元素的
  3. */

  4. import java.util.*;

  5. public class TestHashSetDemo {

  6.         public static void main(String[] args) {
  7.                
  8.                 HashSet mySet = new HashSet();
  9.                 for(int i = 1; i < 10; i++) {
  10.                         boolean flag = mySet.add(new Person01(16 + i, "java" + i));
  11.                         System.out.println(flag);
  12.                         if(i == 9) {
  13.                                 System.out.println(mySet.add(new Person01(16 + i, "java" + i)));
  14.                         }
  15.                 }
  16.                
  17.         }

  18. }

  19. class Person01 {
  20.         private String name;
  21.         private int age;
  22.         Person01(int age, String name) {
  23.                 this.name = name;
  24.                 this.age = age;
  25.         }
  26.         public int hashCode() {
  27.                 System.out.println("ok");
  28.                 //return 1;
  29.                 return name.hashCode() + age*5;
  30.         }
  31.         public boolean equals(Object obj) {
  32.                 //System.out.println("ok11111");
  33.                 Person01 p = (Person01)obj;
  34.                 if(this.age == p.age && this.name.equals(p.name)) {
  35.                         return true;
  36.                 }
  37.                 return false;
  38.         }
  39. }
  40. 由打印的内容可以看出
  41. 1.在未覆写hashcode和equals方法时,打印的内容全部是true(说明一全部加入mySet容器中)
  42. 2.只覆写hashcode方法时,不管返回的是1还是不同的整数,打印的内容也全部是true
  43. 3.既覆写hashcode和equals方法,最后一个元素没有添加进去
  44. 由此可得出在向HashSet容器添加元素时,首先根据hashCode方法判断是不是相同的哈希值,如果相同,则在调用equals方法判断,在未覆写equals方法时,调用的是Object中的equals方法
  45. 比较的是两个对像的地址值(两个new出来的对象的地址值不可能相同),覆写equals方法后,则根据你的设定判断两个对象是否相同
复制代码

点评

不对不对,漏洞无处不在么?  发表于 2013-1-21 21:24

评分

参与人数 1技术分 +1 收起 理由
Rancho_Gump + 1 赞一个!

查看全部评分

回复 使用道具 举报
IC-月辰 发表于 2013-1-21 17:13
问题是不复写hashCode()方法的,也就是说,有没有可能出现这种情况,不一样的两个对象的默认hashCode值是 ...

摘自百度
  1. 哈希算法将任意长度的二进制值映射为固定长度的较小二进制值,这个小的二进制值称为哈希值。哈希值是一段数据唯一且极其紧凑的数值表示形式。如果散列一段明文而且哪怕只更改该段落的一个字母,随后的哈希都将产生不同的值。要找到散列为同一个值的两个不同的输入,在计算上是不可能的,所以数据的哈希值可以检验数据的完整性。
  2. 哈希表是根据设定的哈希函数H(key)和处理冲突方法将一组关键字映象到一个有限的地址区间上,并以关键字在地址区间中的象作为记录在表中的存储位置,这种表称为哈希表或散列,所得存储位置称为哈希地址或散列地址。作为线性数据结构与表格和队列等相比,哈希表无疑是查找速度比较快的一种。
复制代码

点评

不完全正确,其实两个不同的对象的哈希值是有可能相等的  发表于 2013-1-21 21:28

评分

参与人数 1技术分 +1 收起 理由
Rancho_Gump + 1 赞一个!

查看全部评分

回复 使用道具 举报
当然有,比如毕老师视频里举得例子。
写好hashCode方法,算“ab”和"ba"元素哈希值是相同的,所以需要再算equals方法比较元素内容是否相同。

双重判断来确定元素的唯一性。
回复 使用道具 举报
郭嘉 中级黑马 2013-1-21 19:15:07
7#
HashSet中重写Hashcode方法和equals方法来确定两个值的哈希地址值是否相同,如果相同,此时就需要在调用自定义类中的equals方法来确定对象中元素是否相同
回复 使用道具 举报
李光耀 发表于 2013-1-21 18:01
当然有,比如毕老师视频里举得例子。
写好hashCode方法,算“ab”和"ba"元素哈希值是相同的,所以需要再算e ...

我是想说在默认hashCode()方法时,两个对象的哈希值也是有可能相等的
回复 使用道具 举报
高浩 中级黑马 2013-1-21 21:51:31
9#
应该不会,创建了一个对象那么它的地址必须是唯一的,要不然会出现不确定性。
Object类中获取的哈希值是根据地址获取,如果你想它按另一种方式来算哈希值
话,你可以覆盖掉方法,写一个子类自定义的。
回复 使用道具 举报
本帖最后由 黑马张英涛 于 2013-1-21 22:38 编辑

哈希算法
用来产生一些数据片段(例如消息或会话项)的哈希值的算法。使用好的哈希算法,在输入数据中所做的更改就可以更改结果哈希值中的所有位;因此,哈希对于检测数据对象(例如消息)中的修改很有用。此外,好的哈希算法使得构造两个相互独立且具有相同哈希的输入不能通过计算方法实现。典型的哈希算法包括 MD2、MD4、MD5 和 SHA-1。哈希算法也称为“哈希函数”。
*...来自百度百科http://baike.baidu.com/view/273836.htm

Hash,简单来讲,是一种将任意长度的输入变换成固定长度的输出,固定长度的输出在“实际应用场景”下可以代表该输入。Hash函数通常被翻译成散列函数。Hash通常用来校验信息的一致性。
Hash函数的实现多种多样,在安全领域应用最为广泛的是SHA-x系列和MDx系列。Hash函数也划分为带密钥的Hash函数和不带密钥的Hash函数,通常所说的Hash函数是不带密钥的Hash函数。这里对Hash算法的实现原理不做更多的探讨。
       由于Hash固定长度输出的特性,必然会存在多个不同输入产生相同输出的情况。如果两个输入串的hash函数的值一样,则称这两个串是一个碰撞(Collision)。在理论范围内,存在一个输出串对应无穷多个输入串,所以碰撞具有其必然性。....来源http://www.cnblogs.com/xuanhun/archive/2012/01/01/2309571.html

2004年8月17日的美国加州圣巴巴拉的国际密码学会议(Crypto’2004)上,来自中国山东大学的王小云教授做了破译MD5、HAVAL-128、 MD4和RIPEMD算法的报告,公布了MD系列算法的破解结果。宣告了固若金汤的世界通行密码标准MD5的堡垒轰然倒塌,引发了密码学界的轩然大波。
令世界顶尖密码学家想象不到的是,破解MD5之后,2005年2月,王小云教授又破解了另一国际密码SHA-1。因为SHA-1在美国等国际社会有更加广泛的应用,密码被破的消息一出,在国际社会的反响可谓石破天惊。换句话说,王小云的研究成果表明了从理论上讲电子签名可以伪造,必须及时添加限制条件,或者重新选用更为安全的密码标准,以保证电子商务的安全。
  MD5验证可执行文件不再可靠的消息
MD5破解工程权威网站是为了公开征集专门针对MD5的攻击而设立的,网站于2004年8月17日宣布:“中国研究人员发现了完整MD5算法的碰撞;Wang,Feng,Lai与Yu公布了MD5、MD4、HAVAL-128、RIPEMD-128几个 Hash函数的碰撞。这是近年来密码学领域最具实质性的研究进展。使用他们的技术,在数个小时内就可以找到MD5碰撞。……由于这个里程碑式的发现,MD5CRK项目将在随后48小时内结束”。......来自百度百科http://baike.baidu.com/view/7636.htm



回复 使用道具 举报
超链接功能怎么不好使啊?。。
回复 使用道具 举报
高浩 发表于 2013-1-21 21:51
应该不会,创建了一个对象那么它的地址必须是唯一的,要不然会出现不确定性。
Object类中获取的哈希值是根 ...

对的,对象的地址肯定是唯一的,这毫无疑问,但是,默认的hashCode()方法将地址通过哈希算法生成的整数型值就一定是唯一的么?  请仔细考虑
回复 使用道具 举报
逆天了,请看顶楼内容{:soso_e129:}
回复 使用道具 举报
谢谢楼主的分享!
回复 使用道具 举报
IC-月辰 发表于 2013-1-22 02:51
对的,对象的地址肯定是唯一的,这毫无疑问,但是,默认的hashCode()方法将地址通过哈希算法生成的整数型 ...

嗯是的,地址本来就不一样,算出的哈希值肯定就不同了
回复 使用道具 举报
高浩 发表于 2013-1-23 14:39
嗯是的,地址本来就不一样,算出的哈希值肯定就不同了

额,请往上看,看顶楼解释
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马