Chinaunix首页 | 论坛 | 博客
  • 博客访问: 742713
  • 博文数量: 130
  • 博客积分: 2951
  • 博客等级: 少校
  • 技术积分: 1875
  • 用 户 组: 普通用户
  • 注册时间: 2010-03-04 18:32
文章分类

全部博文(130)

文章存档

2013年(1)

2012年(129)

分类: Java

2012-02-27 13:20:25

1. 重写equals时hashCode方法也要重写

2. 集合中两个对象比较的顺序:先调用hashCode(),然后调用equals()

3. hashCode相等时,继续调用equals,表示两个对象可能相等可能不相等;

4. hashCode不相等时不调用equals,表示两个对象一定不相等;

另外,在HashMap中,HashCode的计算,是用来定位我们的键值对应该放到Hash表中哪个格子中的关键属性。而这个HashCode的计算方法是调用的各个对象自己的实现的hashCode()方法。而这个方法是在Object对象中定义的,所以我们自己定义的类如果要在集合中使用的话,就需要正确的覆写hashCode() 方法。下面就介绍一下应该如何正确覆写hashCode()方法。设计hashCode()时最重要的因素就是:无论何时,对同一个对象调用hashCode()都应该生成同样的值。如果在将一个对象用put()方法添加进HashMap时产生一个hashCode()值,而用get()取出时却产生了另外一个hashCode()值,那么就无法重新取得该对象了。所以,如果你的hashCode()方法依赖于对象中易变的数据,那用户就要小心了,因为此数据发生变化时,hashCode()就会产生一个不同的hash码,相当于产生了一个不同的“键”。
   此外,也不应该使hashCode()依赖于具有唯一性的对象信息,尤其是使用this的值,这只能产生很糟糕的hashCode()。因为这样做无法生成一个新的“键”,使之与put()种原始的“键值对”中的“键”相同。例如,如果我们不覆写ObjecthashCode()方法,那么调用该方法的时候,就会调用ObjecthashCode()方法的默认实现。ObjecthashCode()方法,返回的是当前对象的内存地址。下次如果我们需要取一个一样的“键”对应的键值对的时候,我们就无法得到一样的hashCode值了。因为我们后来创建的“键”对象已经不是存入HashMap中的那个内存地址的对象了。
  1. package intro.collections;

  2. import java.util.*;
  3. //身份证类
  4. class Code{
  5.     final int id;//身份证号码已经确认,不能改变
  6.     Code(int i){
  7.         id=i;
  8.     }
  9.     //身份号号码相同,则身份证相同
  10.     public boolean equals(Object anObject) {
  11.         if (anObject instanceof Code){
  12.             Code other=(Code) anObject;
  13.             return this.id==other.id;
  14.         }
  15.         return false;
  16.     }
  17.     public String toString() {
  18.         return "身份证:"+id;
  19.     }    
  20. }
  21. //人员信息类
  22. class Person {
  23.     Code id;// 身份证
  24.     String name;// 姓名
  25.     public Person(String name, Code id) {
  26.         this.id=id;
  27.         this.name=name;
  28.     }
  29.     //如果身份证号相同,就表示两个人是同一个人
  30.     public boolean equals(Object anObject) {
  31.         if (anObject instanceof Person){
  32.             Person other=(Person) anObject;
  33.             return this.id.equals(other.id);
  34.         }
  35.         return false;
  36.     }
  37.     public String toString() {
  38.         return "姓名:"+name+" 身份证:"+id.id+"\n";
  39.     }
  40. }
  41. public class HashCodeTest {
  42.     public static void main(String[] args) {
  43.         HashMap map=new HashMap();
  44.         Person p1=new Person("张三",new Code(123));
  45.         map.put(p1.id,p1);//我们根据身份证来作为key值存放到Map中
  46.         Person p2=new Person("李四",new Code(456));
  47.         map.put(p2.id,p2);
  48.         Person p3=new Person("王二",new Code(789));
  49.         map.put(p3.id,p3);
  50.         System.out.println("HashMap 中存放的人员信息:\n"+map);
  51.         // 张三 改名为:张山 但是还是同一个人。
  52.         Person p4=new Person("张山",new Code(123));
  53.         map.put(p4.id,p4);
  54.         System.out.println("张三改名后 HashMap 中存放的人员信息:\n"+map);
  55.         //查找身份证为:123 的人员信息
  56.         System.out.println("查找身份证为:123 的人员信息:"+map.get(new Code(123)));
  57.     }
  58. }
结果为:
HashMap 中存放的人员信息:
{身份证:456=姓名:李四 身份证:456
, 身份证:123=姓名:张三 身份证:123
, 身份证:789=姓名:王二 身份证:789
}
张三改名后 HashMap 中存放的人员信息:
{身份证:456=姓名:李四 身份证:456
, 身份证:123=姓名:张三 身份证:123
, 身份证:123=姓名:张山 身份证:123
, 身份证:789=姓名:王二 身份证:789
}
查找身份证为:123 的人员信息:null

例子的输出结果表示,我们所做的更新和查找操作都失败了。失败的原因就是我们的身份证类:Code 没有覆写hashCode()方法。这个时候,当查找一样的身份证号码的键值对的时候,使用的是默认的对象的内存地址来进行定位。这样,后面的所有的身份证号对象new Code(123) 产生的hashCode()值都是不一样的。所以导致操作失败。

下面,我们给Code类加上hashCode()方法,然后再运行一下程序看看:

  1. class Code{
  2.     final int id;//身份证号码已经确认,不能改变
  3.     Code(int i){
  4.         id=i;
  5.     }
  6.     //身份号号码相同,则身份证相同
  7.     public boolean equals(Object anObject) {
  8.         if (anObject instanceof Code){
  9.             Code other=(Code) anObject;
  10.             return this.id==other.id;
  11.         }
  12.         return false;
  13.     }
  14.     public String toString() {
  15.         return "身份证:"+id;
  16.     }    
  17.     //覆写hashCode方法,并使用身份证号作为hash值
  18.     public int hashCode(){
  19.         return id;
  20.     }
  21. }

结果就为:
HashMap 中存放的人员信息:
{身份证:456=姓名:李四 身份证:456
, 身份证:789=姓名:王二 身份证:789
, 身份证:123=姓名:张三 身份证:123
}
张三改名后 HashMap 中存放的人员信息:
{身份证:456=姓名:李四 身份证:456
, 身份证:789=姓名:王二 身份证:789
, 身份证:123=姓名:张山 身份证:123
}
查找身份证为:123 的人员信息:姓名:张山 身份证:123




阅读(1251) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~