天天看点

JAVA中重写equals()方法为什么要重写hashcode()方法说明

重写hashCode()时最重要的原因就是:无论何时,对同一个对象调用hashCode()都应该生成同样的值。如果在将一个对象用put()方法添 加进HashMap时产生一个hashCode()值,而用get()取出时却产生了另外一个 hashCode()值,那么就无法重新取得该对象了。所以,如果你的hashCode()方法依赖于对象中易变的数据,那用户就要小心了,因为此数据发 生变化时,hashCode()就会产生一个不同的hash码,相当于产生了一个不同的“键”。 

      Object的hashCode()方法,返回的是当前对象的内存地址。下次如果我们需要取一个一样的“键”对应的键值对的时候,我们就无法得到一样的 hashCode值了。因为我们后来创建的“键”对象已经不是存入HashMap中的那个内存地址的对象了。 

      我们看一个简单的例子,就能更加清楚的理解上面的意思。假定我们写了一个类:Person (人),我们判断一个对象“人”是否指向同一个人,只要知道这个人的×××号一直就可以了。 

      先来个没有重写Code类的hashcode()的例子吧,看看是什么效果:

Java代码  

  1. package com.fit;  
  2. import java.util.HashMap;  
  3. /** 
  4.  * ×××类 
  5.  *  
  6.  * @author ZYD 
  7.  */  
  8. public class Code {  
  9.     /** 
  10.      * ×××号码,一旦确定就不能更改 
  11.      */  
  12.     private final int id;  
  13.     public int getId() {  
  14.         return id;  
  15.     }  
  16.      * 通过构造方法确定×××号码 
  17.      *  
  18.      * @param id 
  19.     public Code(int id) {  
  20.         this.id = id;  
  21.      * 重写equals()方法 
  22.     public boolean equals(Object o) {  
  23.         // 如果地址一样,则两个对象相同  
  24.         if (this == o) {  
  25.             return true;  
  26.         }  
  27.         // 如果两个对象是同一类型,则比较其属性值是否都相同。如果都相同,则说明两个对象也相同;否则,说明这两个对象不相同。  
  28.         if (o instanceof Code) {  
  29.             Code co = (Code) o;  
  30.             boolean b = (co.id == this.id);  
  31.             return b;  
  32.         return false;  
  33.      * 重写toString()方法 
  34.     public String toString() {  
  35.         return "【×××】:" + id;  
  36.      * 测试 
  37.      * @param args 
  38.     public static void main(String[] args) {  
  39.          HashMap<Code, Person> map = new HashMap<Code, Person>();  
  40.          Person p1 = new Person(new Code(10001),"张三");  
  41.          Person p2 = new Person(new Code(10002),"李四");  
  42.          map.put(p1.getCode(), p1);  
  43.          map.put(p2.getCode(), p2);  
  44.          System.out.println("HashMap 中存放的人员信息:\n"+map);  
  45.          //张三改名为张山,×××号不变。  
  46.          Person p3 = new Person(new Code(10001),"张山");  
  47.          map.put(p3.getCode(), p3);  
  48.          System.out.println("张三改名为张山后 HashMap 中存放的人员信息:\n"+map);  
  49.          //查找×××为10001 的人员信息  
  50.          System.out.println("查找×××为:10001 的人员信息:"+map.get(new Code(10001)));  
  51. }  
  52.  * 人类 
  53.  * @author Administrator 
  54.  * 
  55. class Person {  
  56.      * 每一个成人都有一个××× 
  57.     private Code code;  
  58.      * 姓名 
  59.     private String name;  
  60.     public Code getCode() {  
  61.         return code;  
  62.     public void setCode(Code code) {  
  63.         this.code = code;  
  64.     public String getName() {  
  65.         return name;  
  66.     public void setName(String name) {  
  67.         this.name = name;  
  68.     public Person() {  
  69.     public Person(Code code, String name) {  
  70.      * 重写equals()方法 当两个人得×××号相同以及姓名相同时,表示这两个人是同一个人。 
  71.         if (o == this) {  
  72.         if (o instanceof Person) {  
  73.             Person p = (Person) o;  
  74.             boolean b = this.code.equals(p.code) && this.name.equals(p.name);  
  75.         return "【姓名】:" + name + "  ";  

运行结果:

HashMap 中存放的人员信息:

{【×××】:10002=【姓名】:李四  , 【×××】:10001=【姓名】:张三  }

张三改名为张山后 HashMap 中存放的人员信息:

{【×××】:10002=【姓名】:李四  , 【×××】:10001=【姓名】:张三  , 【×××】:10001=【姓名】:张山  }

查找×××为:10001 的人员信息:null

从上面的结果可以看出:

我们所做的更新和查找操作都失败了。失败的原因就是我们的×××类: Code 没有覆写 hashCode() 方法。这个时候,当查找一样的×××号码的键值对的时候,使用的是默认的对象的内存地址来进行定位。这样,后面的所有的×××号对象

new Code(10001) 产生的 hashCode () 值都是不一样的,所以导致操作失败。

 重写Code类的hashcode(),代码上:

  1.      * 重写hashcode()方法,以×××号码作为hash码。 
  2.      * @return 
  3.     public int hashCode() {  

运行效果:

{【×××】:10001=【姓名】:张三  , 【×××】:10002=【姓名】:李四  }

{【×××】:10001=【姓名】:张山  , 【×××】:10002=【姓名】:李四  }

查找×××为:10001 的人员信息:【姓名】:张山