【哈希码】对hashCode()的疑问。 本帖最后由 xuxinloveyeshou 于 2011-07-28 12:10:59 编辑 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 1. '=='是用来比较两个变量(基本类型和对象类型)的值是否相等的, 如果两个变量是基本类型的,那很容易,直接比较值就可以了。如果两个变量是对象类型的,那么它还是比较值,只是它比较的是这两个对象在栈中的引用(即地址)。 对象是放在堆中的,栈中存放的是对象的引用(地址)。由此可见'=='是对栈中的值进行比较的。如果要比较堆中对象的内容是否相同,那么就要重写equals方法了。 2. Object类中的equals方法就是用'=='来比较的,所以如果没有重写equals方法,equals和==是等价的。 通常我们会重写equals方法,让equals比较两个对象的内容,而不是比较对象的引用(地址)因为往往我们觉得比较对象的内容是否相同比比较对象的引用(地址)更有意义。 3. Object类中的hashCode是返回对象在内存中地址转换成的一个int值(可以就当做地址看)。所以如果没有重写hashCode方法,任何对象的hashCode都是不相等的。通常在集合类的时候需要重写hashCode方法和equals方法,因为如果需要给集合类(比如:HashSet)添加对象,那么在添加之前需要查看给集合里是否已经有了该对象,比较好的方式就是用hashCode。 4. 注意的是String、Integer、Boolean、Double等这些类都重写了equals和hashCode方法,这两个方法是根据对象的内容来比较和计算hashCode的。(详细可以查看jdk下的String.java源代码),所以只要对象的基本类型值相同,那么hashcode就一定相同。 5. equals()相等的两个对象,hashcode()一般是相等的,最好在重写equals()方法时,重写hashcode()方法; equals()不相等的两个对象,却并不能证明他们的hashcode()不相等。换句话说,equals()方法不相等的两个对象,hashcode()有可能相等。 反过来:hashcode()不等,一定能推出equals()也不等;hashcode()相等,equals()可能相等,也可能不等。在object类中,hashcode()方法是本地方法,返回的是对象的引用(地址值),而object类中的equals()方法比较的也是两个对象的引用(地址值),如果equals()相等,说明两个对象地址值也相等,当然hashcode()也就相等了。 以下是测试代码。 public class Equals_HashCode { 2. public static void main(String[] args) { 3. String a = new String("str"); 4. String b = new String("str"); 5. System.out.println(a==b); 6. System.out.println(a.equals(b)); 7. System.out.println(a.hashCode()); 8. System.out.println(b.hashCode()); 9. // 输出 false true 114225 114225 10. class A{ 11. String str; 12. int i; 13. public A(String str, int i) { 14. super(); 15. this.str = str; 16. this.i = i; 17. } 18. } 19. A aA = new A("str",1); 20. A bA = new A("str",1); 21. System.out.println(aA==bA); 22. System.out.println(aA.equals(bA)); 23. System.out.println(aA.hashCode()); 24. System.out.println(bA.hashCode()); 25. // 输出 false false 6413875 21174459 26. class B{ 27. String str; 28. public B(String str){ 29. this.str = str; 30. } 31. } 32. B aB = new B("str"); 33. B bB = new B("str"); 34. System.out.println(aB==bB); 35. System.out.println(aB.equals(bB)); 36. System.out.println(aB.hashCode()); 37. System.out.println(bB.hashCode()); 38. // 输出 false false 827574 17510567 39. class C{ 40. int i; 41. public C(int i){ 42. this.i = i; 43. } 44. } 45. C aC = new C(1); 46. C bC = new C(1); 47. System.out.println(aC==bC); 48. System.out.println(aC.equals(bC)); 49. System.out.println(aC.hashCode()); 50. System.out.println(bC.hashCode()); 51. //输出 false false 27744459 28737396 52. } 53. 54.} 第二句翻译的有问题吧,equals(Object)为true,hashcode并不一定相等,我一直都是这么理解的.只有equals(Object)和hashcode都一致,才能认为两个对象完全相等. 写得好多,我看得似懂非懂的。第3点你说到了任何对象如果没有重写hashCode方法,它们的hashCode都不相等。第5点你说到了equals()相等的两个对象,hashcode()一般是相等的;_______但是这两个相等的对象如果没有重写了hashCode方法,调用的还是Object的本地方法hashCode即返回对象的内存地址,这两个对象在内存中的地址肯定不一样,所以hashCode也不一样啊。 额,我理解您的第3点和第5点觉得有点矛盾,可能我理解错了吧。我先试试您的测试代码。 看到很多地方都说equals相等的两个对象的hashCode一般相等啊,我也搞糊涂了 重写了equals方法,就不一定相等了! 是不是重写了equals()方法也要同时重写hashCode()方法?这句话是对的. 运行了您的测试代码后,感觉懂了。对您的第5点, equals()相等的两个对象,hashcode()一般是相等的,最好在重写equals()方法时,重写hashcode()方法;-------您的意思是调用Object的equals(),即不是重写比较对象内容而是比较对象的内存地址,那么equals相等也就表明内存地址相同即hashCode相等。我的理解有问题吗 为什么StringBuffer没有实现Cloneable接口 学习计算机 获取jsp页面绝对路径的问题 异常问题求助 怎么把string转换成char的数据类型? 安装 JBuilder9后在web中web Application, Servlet,Java Server Page等为什么都不能使用?在线等! 十万火急的求助华容道的源程序 请问这个程序错在那里啊?(是一个服务器端程序用来接受客户端信息) 小弟初学Java有一个疑问!!! 哪里有Jbuilder5手册下载? java.lang.ClassNotFoundException错误 一台机器上两个UDP端口都为0不会冲突吗?
对象是放在堆中的,栈中存放的是对象的引用(地址)。由此可见'=='是对栈中的值进行比较的。如果要比较堆中对象的内容是否相同,那么就要重写equals方法了。
2. Object类中的equals方法就是用'=='来比较的,所以如果没有重写equals方法,equals和==是等价的。
通常我们会重写equals方法,让equals比较两个对象的内容,而不是比较对象的引用(地址)因为往往我们觉得比较对象的内容是否相同比比较对象的引用(地址)更有意义。
3. Object类中的hashCode是返回对象在内存中地址转换成的一个int值(可以就当做地址看)。所以如果没有重写hashCode方法,任何对象的hashCode都是不相等的。通常在集合类的时候需要重写hashCode方法和equals方法,因为如果需要给集合类(比如:HashSet)添加对象,那么在添加之前需要查看给集合里是否已经有了该对象,比较好的方式就是用hashCode。
4. 注意的是String、Integer、Boolean、Double等这些类都重写了equals和hashCode方法,这两个方法是根据对象的内容来比较和计算hashCode的。(详细可以查看jdk下的String.java源代码),所以只要对象的基本类型值相同,那么hashcode就一定相同。
5. equals()相等的两个对象,hashcode()一般是相等的,最好在重写equals()方法时,重写hashcode()方法; equals()不相等的两个对象,却并不能证明他们的hashcode()不相等。换句话说,equals()方法不相等的两个对象,hashcode()有可能相等。 反过来:hashcode()不等,一定能推出equals()也不等;hashcode()相等,equals()可能相等,也可能不等。在object类中,hashcode()方法是本地方法,返回的是对象的引用(地址值),而object类中的equals()方法比较的也是两个对象的引用(地址值),如果equals()相等,说明两个对象地址值也相等,当然hashcode()也就相等了。
以下是测试代码。 public class Equals_HashCode {
2. public static void main(String[] args) {
3. String a = new String("str");
4. String b = new String("str");
5. System.out.println(a==b);
6. System.out.println(a.equals(b));
7. System.out.println(a.hashCode());
8. System.out.println(b.hashCode());
9. // 输出 false true 114225 114225
10. class A{
11. String str;
12. int i;
13. public A(String str, int i) {
14. super();
15. this.str = str;
16. this.i = i;
17. }
18. }
19. A aA = new A("str",1);
20. A bA = new A("str",1);
21. System.out.println(aA==bA);
22. System.out.println(aA.equals(bA));
23. System.out.println(aA.hashCode());
24. System.out.println(bA.hashCode());
25. // 输出 false false 6413875 21174459
26. class B{
27. String str;
28. public B(String str){
29. this.str = str;
30. }
31. }
32. B aB = new B("str");
33. B bB = new B("str");
34. System.out.println(aB==bB);
35. System.out.println(aB.equals(bB));
36. System.out.println(aB.hashCode());
37. System.out.println(bB.hashCode());
38. // 输出 false false 827574 17510567
39. class C{
40. int i;
41. public C(int i){
42. this.i = i;
43. }
44. }
45. C aC = new C(1);
46. C bC = new C(1);
47. System.out.println(aC==bC);
48. System.out.println(aC.equals(bC));
49. System.out.println(aC.hashCode());
50. System.out.println(bC.hashCode());
51. //输出 false false 27744459 28737396
52. }
53.
54.}
第3点你说到了任何对象如果没有重写hashCode方法,它们的hashCode都不相等。
第5点你说到了equals()相等的两个对象,hashcode()一般是相等的;_______但是这两个相等的对象如果没有重写了hashCode方法,调用的还是Object的本地方法hashCode即返回对象的内存地址,这两个对象在内存中的地址肯定不一样,所以hashCode也不一样啊。
额,我理解您的第3点和第5点觉得有点矛盾,可能我理解错了吧。我先试试您的测试代码。
重写了equals方法,就不一定相等了!
对您的第5点, equals()相等的两个对象,hashcode()一般是相等的,最好在重写equals()方法时,重写hashcode()方法;-------您的意思是调用Object的equals(),即不是重写比较对象内容而是比较对象的内存地址,那么equals相等也就表明内存地址相同即hashCode相等。
我的理解有问题吗