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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 我自信我很牛 中级黑马   /  2013-3-16 20:54  /  1601 人查看  /  4 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 烟磊磊 于 2013-3-16 23:53 编辑

在重写equals方法时,为什么要重写hashcode,最好解释一下,最好能解释一下,在内存中hashcode是怎么用的。

评分

参与人数 1技术分 +1 收起 理由
贾文泽 + 1

查看全部评分

4 个回复

倒序浏览
public int hashCode()返回该对象的哈希码值。支持该方法是为哈希表提供一些优点,例如,java.util.Hashtable 提供的哈希表。
hashCode 的常规协定是:

在 Java 应用程序执行期间,在同一对象上多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是对象上 equals 比较中所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。
如果根据 equals(Object) 方法,两个对象是相等的,那么在两个对象中的每个对象上调用 hashCode 方法都必须生成相同的整数结果。
以下情况不 是必需的:如果根据 equals(java.lang.Object) 方法,两个对象不相等,那么在两个对象中的任一对象上调用 hashCode 方法必定会生成不同的整数结果。但是,程序员应该知道,为不相等的对象生成不同整数结果可以提高哈希表的性能。
实际上,由 Object 类定义的 hashCode 方法确实会针对不同的对象返回不同的整数。(这一般是通过将该对象的内部地址转换成一个整数来实现的,但是 JavaTM 编程语言不需要这种实现技巧。)

public boolean equals(Object obj)指示某个其他对象是否与此对象“相等”。
equals 方法在非空对象引用上实现相等关系:

自反性:对于任何非空引用值 x,x.equals(x) 都应返回 true。
对称性:对于任何非空引用值 x 和 y,当且仅当 y.equals(x) 返回 true 时,x.equals(y) 才应返回 true。
传递性:对于任何非空引用值 x、y 和 z,如果 x.equals(y) 返回 true,并且 y.equals(z) 返回 true,那么 x.equals(z) 应返回 true。
一致性:对于任何非空引用值 x 和 y,多次调用 x.equals(y) 始终返回 true 或始终返回 false,前提是对象上 equals 比较中所用的信息没有被修改。
对于任何非空引用值 x,x.equals(null) 都应返回 false。
Object 类的 equals 方法实现对象上差别可能性最大的相等关系;即,对于任何非空引用值 x 和 y,当且仅当 x 和 y 引用同一个对象时,此方法才返回 true(x == y 具有值 true)。

注意:当此方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。


参数:
obj - 要与之比较的引用对象。
返回:
如果此对象与 obj 参数相同,则返回 true;否则返回 false。


LZ可以参考下


回复 使用道具 举报
     重写equals不一定要重写hashcode方法,之所以重写hashcode方法,是防止自定义对象在存入HashSet或是HashMap集合的时候,要保证对象唯一性的判断依据而已。这个是底层的调用过程,每次存入的对象(第一个除外)都会先调用hashcode方法进行比较,如果不一致直接存入集合,如果hashcode相同的话,就在比较equals方法。
    其实hashcode和equals方法的方法体是我们自己定义的,换句话说,比较方式(依据)是我们自己定义的。
    (主要记住先执行hashcode方法在执行equal方法,对啦,这些方法都是自动被调用的,就够啦)
回复 使用道具 举报
只有类的实例对象要被采用哈希算法进行存入和检索时,这个类才需要按要求复写hashCode()方法,即使程序可能暂时不会用到当前类的hashCode()方法,但是为提供一个hashCode()方法也不会有什么不好,没准以后什么时候就会用到这个方法,所以通常要求hashCode()和equals()两者一并被覆盖。简单来说,就是默认的hashCode()方法可能不是我们需要的,而且这种算法可能会导致两个不同的对象获得的哈希值会相同,那么就会产生意想不到的结果,所以需要覆写hashCode()方法。
需要注意的是,当对象每次调用方法时,会先调用hashCode()的方法:
  1. import java.util.ArrayList;
  2. import java.util.Collection;
  3. import java.util.HashSet;

  4. public class ReflectTest2 {
  5.         public static void main(String [] args){
  6.                 Collection cons = new HashSet();
  7.                 ReflectPoint pt1 = new ReflectPoint(3,3);
  8.                 ReflectPoint pt2 = new ReflectPoint(5,5);
  9.                 ReflectPoint pt3 = new ReflectPoint(3,3);

  10.                 cons.add(pt1);
  11.                 cons.add(pt2);
  12.                 cons.add(pt3);
  13.                 cons.add(pt1);
  14.                 cons.remove(pt1);
  15.                 System.out.println(cons.size());
  16.         }
  17. }

  18. public class ReflectPoint {
  19.         private int x;
  20.         public int y;
  21.         public String str1 = "ball";
  22.         public String str2 = "basketball";
  23.         public String str3 = "itcast";
  24.        
  25.         public ReflectPoint(int x, int y) {
  26.                 super();
  27.                 this.x = x;
  28.                 this.y = y;
  29.         }
  30.        
  31.         public int hashCode() {
  32.                 final int prime = 31;
  33.                 int result = 1;
  34.                 result = prime * result + x;
  35.                 result = prime * result + y;
  36.                 //System.out.println("demo...");//测试
  37.                 return result;
  38.         }

  39.         public boolean equals(Object obj) {
  40.                 if (this == obj)
  41.                         return true;
  42.                 if (obj == null)
  43.                         return false;
  44.                 if (getClass() != obj.getClass())
  45.                         return false;
  46.                 ReflectPoint other = (ReflectPoint) obj;
  47.                 if (x != other.x)
  48.                         return false;
  49.                 if (y != other.y)
  50.                         return false;
  51.                 return true;
  52.         }

  53.         public String toString(){
  54.                 return str1+";" + str2 + ";" + str3;
  55.         }
  56. }
复制代码
你把测试的那个注释打开,你就看到现象了。

评分

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

查看全部评分

回复 使用道具 举报
HashCode  和equals 方法都从Object 继承的方法,在没有重写的情况下,这两者比较 的都是对象的地址。我们在往HashSet或是HashMap集合的时候放对象的时候,判断这两个对象是否相等,是先判断 hashCode 是否相等,如过不等则直接存入,如果hashcode 相等,再判断equals 是否相等,equals相等,则表示是同一个对象。不在 存入。如果不等则存入对象。但是在实际的应用中,我们判断两个对象,是否相等,需要判断的是内容,而不是地址,因此要重写equals。但是根据判断规则,它先判断的是hashCode 而不是equals.在hashCode 不同的情况下,就直接存入了,不再调用equals 了,因此,为了达到,我们比较内容的目标,重写equals 方法的时候,最好重写hashCode 已达到我们正确的比较结果。

评分

参与人数 1技术分 +1 收起 理由
贾文泽 + 1

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马