Java中的hashCode二

来源:互联网 发布:windows snmp 编辑:程序博客网 时间:2024/05/22 13:30

 equals方法和hashCode方法

  在有些情况下,我们在设计一个类的时候,会重写equals 方法,比如String类,但是千万要注意,在重写equals 方法的同时,必须重写hashCode方法,为什么?

  下面看一个例子:

package com.zd.test;public class People {private String name;private int age;public People(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic boolean equals(Object paramObject) {// TODO Auto-generated method stubif(this == paramObject){return true; //先检查是否其自反性,后比较paramObject是否为空。这样效率高}if(paramObject == null){return false;}if(paramObject instanceof People){People temp  = (People)paramObject;if(temp.getName().equals(this.name) && temp.getAge() == this.age){return true;}else{return false;}}else{return false;}}}


package com.zd.test;import java.util.HashMap;public class Main {/** * @param args */public static void main(String[] args) {// TODO Auto-generated method stubPeople p1 = new People("jack", 12);System.out.println(p1.hashCode());HashMap<People, Integer> hashMap = new HashMap<People, Integer>();hashMap.put(p1, 1);System.out.println(hashMap.get(new People("jack", 12)));}}

   在这里只重写了equals 方法,也就是说如果俩个People对象,如果他们姓名和年龄相等,则认为同一个人。

   这段代码的意愿是输出为“1”,但是事实上他输出为 “null“。为什么?原因就在于重写equals方法的同时没有重写hashCode方法。

   虽然通过重写equals方法使得逻辑上姓名和年龄相同的俩个对象为相等的对象,但是要知道默认情况下,hashCode方法是将对象的存储地址进行映射。那么上述代码输出为

”null“就不奇怪了。原因很简单,p1指向对象和

System.out.println(hashMap.get(new People("jack", 12)));

 这句话中的 new People("Jack", 12) 不是同一个对象,他们的存储地址肯定不同。

  下面是HashMap的get方法的具体实现:

public V get(Object paramObject)  {    if (paramObject == null) {      return getForNullKey();    }    Entry localEntry = getEntry(paramObject);    return null == localEntry ? null : localEntry.getValue();  }

   所以在hashMap 进行get操作的时候,因为得到的hashcode值不同(注意:上述代码在某些情况下会得到相同的hashCode,不过这种概率比较小,因为虽然俩个对象的地

址不同,但是也有可能获得相同的hashCode),所以导致在get方法中for循环不会执行,直接返回null。

  因此如果想要上述代码输出1 ,很简单,只要重写hashCode方法,让hashCode方法和equals 方法保持逻辑一致。

package com.zd.test;public class People {private String name;private int age;public People(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic int hashCode() {// TODO Auto-generated method stubreturn name.hashCode() * 37 + age;}@Overridepublic boolean equals(Object paramObject) {// TODO Auto-generated method stubif(this == paramObject){return true; //先检查是否其自反性,后比较paramObject是否为空。这样效率高}if(paramObject == null){return false;}if(paramObject instanceof People){People temp  = (People)paramObject;if(temp.getName().equals(this.name) && temp.getAge() == this.age){return true;}else{return false;}}else{return false;}}}

   在程序执行期间,只要equals方法的比较操作用到的信息没有被修改,那么对这同一个对象调用多次,hashCode方法必须始终如一的返回一个整数。

  如果俩个对象根据equals 方法比较是相等的,则hashCode方法不一定得返回相同的整数;

  如果 俩个对象根据equals方法比较是不等的,则hashCode方法不一定得返回不同的整数。

  设计hashCode时最重要的因素是:无论何时,对同一个对象调用hashCode都应该产生同样的值,如果在向一个Map中put时用的是一个值,而get的时候又是另一个值,那么

就无法获取到该对象了。
 




0 0