黑马程序员技术交流社区

标题: 关于equals()方法和hashcode() [打印本页]

作者: 韩军博    时间: 2011-12-5 14:02
标题: 关于equals()方法和hashcode()
本帖最后由 韩军博 于 2011-12-6 12:58 编辑

两个对象值相同(x.equals(y) == true),但却可有不同的hash code,这句话对不对? 请各位详细的解释一下
作者: 侯伟浩    时间: 2011-12-5 14:20
对。在进行两个对象间比较的时候,首先会调用hashcode方法比较两个对象的哈希码,如果两个哈希码相等就不会再调用equals方法了,如果两个哈希码不等就会调用equals再次比较。
作者: 侯伟浩    时间: 2011-12-5 14:22
补充一点:哈希码是决定对象的存放位置的。所以两个对象的值相等不一定哈希码相等,哈希码相等值一定相等。
作者: 颜秉武    时间: 2011-12-5 14:24
这种解释是错误的,两个对象的equals相同则证明他俩是一个类的两个对象
而hashCode方法返回的大多数是对象的内存地址
或者返回自己改写的哈希值
如一个人类中有两个属性,年龄,和名字,这个类有两个对象,这两个对象的equals一定是相等的
而他们的哈希值也是他们的内存地址,或者我们为之改写的特征哈希值,例如,年龄了,或者姓名的首字母字典顺序了,等等,既然两个对象是一个类,所以这些一定相同
从而得出两个对象equals相等,Hash Code一定相等
作者: 刘基军    时间: 2011-12-5 14:30
【以下个人l理解,仅供参考,^_^】
equals若相等,则hashcode应该也一致,
equals若不相等,则hashcode可能一致。(我们应该,为不相等的对象生成不同hashcode,以提高哈希表的性能)

以HashSet集合为例(HashSet集合里面的元素,不重复),当你通过add(a)方法向集合里添加a元素时,接着,
1.首先,得到元素a的hashcode,然后与已存在的元素的hashcode进行比较。如果不一致,则可以存储元素a;否则还需进行equals()方法的比较,
2.当元素a与具有相同hashcode的元素,进行equals()比较后。如果为false,表示元素不重复,则可以存储元素a;如果为true,则表示元素重复,集合就不会存储元素a。
作者: 常登凯    时间: 2011-12-5 15:26
本帖最后由 常登凯 于 2011-12-5 15:47 编辑

哈希码不同时对象有可能相同,也有可能不同,也就是楼主所说的“两个对象值相同(x.equals(y) == true),但却可有不同的hash code”
作者: 刘海涛    时间: 2011-12-5 15:32
先看代码:

  1. /**
  2. * Dog
  3. * @author Administrator
  4. *
  5. */
  6. public class Dog {
  7.         private String name;

  8.         public Dog(String name) {
  9.                 this.name =  name;
  10.         }
  11.         public String getName() {
  12.                 return name;
  13.         }

  14.         public void setName(String name) {
  15.                 this.name = name;
  16.         }

  17.         @Override
  18.         public int hashCode() {
  19.                 final int prime = 31;
  20.                 int result = 1;
  21.                 result = prime * result + ((name == null) ? 0 : name.hashCode());
  22.                 return result;
  23.         }

  24.         @Override
  25.         public boolean equals(Object obj) {
  26.                 if (this == obj)
  27.                         return true;
  28.                 if (obj == null)
  29.                         return false;
  30.                 Person other = (Person) obj;
  31.                 if (name == null) {
  32.                         if (other.getName() != null)
  33.                                 return false;
  34.                 } else if (!name.equals(other.getName()))
  35.                         return false;
  36.                 return true;
  37.         }
  38. }





  39. /**
  40. * Person
  41. * @author Administrator
  42. *
  43. */

  44. public class Person extends Object {
  45.         private String name;

  46.         public Person(String name) {
  47.                 this.name = name;
  48.         }
  49.        
  50.         public String getName() {
  51.                 return name;
  52.         }

  53.        
  54.         public void setName(String name) {
  55.                 this.name = name;
  56.         }

  57.         @Override
  58.         public int hashCode() {
  59.                 final int prime = 32;
  60.                 int result = 1;
  61.                 result = prime * result + ((name == null) ? 0 : name.hashCode());
  62.                 return result;
  63.         }

  64.         @Override
  65.         public boolean equals(Object obj) {
  66.                 if (this == obj)
  67.                         return true;
  68.                 if (obj == null)
  69.                         return false;
  70.                 Dog other = (Dog) obj;
  71.                 if (name == null) {
  72.                         if (other.getName() != null)
  73.                                 return false;
  74.                 } else if (!name.equals(other.getName()))
  75.                         return false;
  76.                 return true;
  77.         }
  78.         /**
  79.          * 测试
  80.          * @param args
  81.          */
  82.         public static void main(String[] args) {
  83.                 Dog dog = new Dog("oudi");
  84.                 Person person = new Person("oudi");
  85.                 System.out.println(dog.equals(person));//运行的结果:true
  86.                 System.out.println(dog.hashCode() != person.hashCode()); //运行的结果:true
  87.         }
  88. }
复制代码
上面运行结果可以说明两个对象值相同(x.equals(y) == true),但却可有不同的hash code,
其实两个类都不相同,但是equals相同。
下面谈谈equals和  hash code:
1.equals
   equals其实是调用对象的equals方法。那么对象我们通常没有写equals方法方法。这里需要了解的是任何对象的都隐式的继承Object .上面我写的Dog类其实是 public class Dog extends Object{} 。 继承Object就有了equals方法。Object的默认的equals方法是比较两个对象的引用是否是同一个对象(就是 dog == person )
Object类equals方法原代码:

  1. boolean equals(Object obj) {
  2.         return (this == obj);
  3.   }
复制代码
我们既然继承了 Object 我们就可以重写Object 的equals方法,当我们使用的时候会调用真实对象的 equals 方法(多态),这个时候你想怎么定义就怎么定义,返回值就是我们得到的结果,你想让2个对象equals怎么相等就怎么相等,Dog 和Person 相等也可以的(例如我上面的代码)。
2.hash code
  一个对象的hashcode也是和equals一样是调用Object的hashCode方法, Object的默认 hashCode是内存的地址。
Object原代码是调用本地的方法,
Object hashCode()方法原代码

  1. public native int hashCode();
复制代码
既然和equals一样,我们只需要重写就可以了,想让我们自己的对象是什么hashcode就是什么hashcode值。


通过equals 和hashcode 了解,其实就是面向对象的多态,其实就是方法的调用。
总结:
两个对象equals 相等,有不同的 hashCode
两个对象hashCode 相同,两个对象equals 不等
两个对象equals 相等,有相同的 hashCode

在实际的应用当中我们一般不会处理的这么复杂. 一般不会对两个不同的类去写 equals。
比如两个person相同,我们只需要重写person的equals方法,一般都按照Person的属性来定义是否相同。如果是Object的默认方法,比较内存是否是一个对象。根据面向对象,我们就不好去维护对象。比如:比较两个人的名字,就是同一个对象。我们只需要调用equals 方法,写好我们自己的逻辑就,可以了。

对象的hahscode的值,在散列算法中非常有用。在集合,大量数据快速查询等等都用会到,所谓的牺牲空间换来速度。

多了解面向对象,这样的问题是很容易想通。java是面向对象语言。
作者: 段波    时间: 2011-12-5 19:06
equals比较是两个对象的内容是否相等,hashCode是根据内存地址换算出来的一个值,当两相对象equals相等时,我们最好让它们的hashCode值也相等,当然如果你不把对象存放入hash集合中也可不考虑hashCode值,还有就是最好不要去修改参与hashcode值计算的字段,以免删除数据时无法真正删除,造成内存泄漏。
作者: 赵燕燕    时间: 2011-12-6 02:05
hasdCose是将对象的内部地址转换成一个整数得来的,也就是对象在内存中的地址。
x.equals(y) == true;能得到true,就说明这个时候equals()方法比较的是内容,
但仍有两个对象,两个地址,所以hashCode值肯定不同




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