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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 谢明 中级黑马   /  2012-2-25 02:15  /  1694 人查看  /  5 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

  1.         //package c08.hashEx;
  2.         import java.util.*;
  3.         //身份证类
  4.         class Code{
  5.                 final int id;//身份证号码已经确认,不能改变
  6.                 Code(int i){
  7.                         id=i;

  8.                 }

  9.                 public boolean equals(Object anObject) {
  10.                         if (anObject instanceof Code){
  11.                                 Code other=(Code) anObject;
  12.                                 return this.id==other.id;
  13.                         }
  14.                         return false;
  15.                 }
  16.                 // hashcode 改到这里就正确了
  17.                 //public int hashCode(){
  18.                 //return id;
  19.                 //}
  20.                 public String toString() {
  21.                         return "身份证:"+id;
  22.                 }

  23.         }
  24.         //人员信息类
  25.         class Person {
  26.                 Code id;// 身份证
  27.                 String name;// 姓名
  28.                 public Person(String name, Code id) {
  29.                         this.id=id;
  30.                         this.name=name;
  31.                 }

  32.                 public boolean equals(Object anObject) {
  33.                         if (anObject instanceof Person){
  34.                                 Person other=(Person) anObject;
  35.                                 return this.id.equals(other.id);
  36.                         }
  37.                         return false;
  38.                 }

  39.                
  40.                 public int hashCode(){
  41.                         return id.id;
  42.                 }
  43.                 public String toString() {
  44.                         return "姓名:"+name+" 身份证:"+id.id+"\n";
  45.                 }
  46.         }
  47.         public class HashCodeEx {
  48.                 public static void main(String[] args) {
  49.                         HashMap map=new HashMap();
  50.                         Person p1=new Person("张三",new Code(123));
  51.                         map.put(p1.id,p1);//根据身份证来作为key值存放到Map中
  52.                         Person p2=new Person("李四",new Code(456));
  53.                         map.put(p2.id,p2);
  54.                         Person p3=new Person("王二",new Code(789));
  55.                         map.put(p3.id,p3);
  56.                         System.out.println("HashMap 中存放的人员信息:\n"+map);
  57.                         // 张三 改名为:张山 但是还是同一个人。
  58.                         Person p4=new Person("张山",new Code(123));
  59.                         map.put(p4.id,p4);
  60.                         System.out.println("张三改名后 HashMap 中存放的人员信息:\n"+map);
  61.                         //查找身份证为:123 的人员信息
  62.                         System.out.println("查找身份证为:123 的人员信息:"+map.get(new Code(123)));
  63.                 }
  64.         }
复制代码
为什么我的hashcode  写到 person 里面就不行了呢  不能判断

5 个回复

倒序浏览
首先理清下思路:
你是想通过  Code对象 来标记判断两个 Person对象  是不是一个人,之后在HashMap中使用 Person对象的Code对象(id)作为键值 ,保证唯一性。由于HashMap,它基于哈希算法进行了优化,原来Map本身是通过equals方法来保证键值的唯一性,但是HashMap有一个特性就是如果 两个键值的 hashcode返回值不一样,那么键值对象绝对是唯一的,也就不用执行equals方法了。

HashCodeEx中的HashMap的键值是 Code 对象,那么就依赖Code类中的hashCode() 和equals(Object obj) 方法来进行判断,但是你在不覆盖hashCode() 的前提下,返回的是基于对象的地址的一个算法值,那么只要是用 new 产生的Code 对象,那么即使是 id 相等,HashCodeEx中的HashMap也会认为是2个不同的键值,那么你的
Person p4=new Person("张山",new Code(123));
                        map.put(p4.id,p4);
语句没有覆盖原先的  p4 对象,而最后一句( System.out.println("查找身份证为:123 的人员信息:"+map.get(new Code(123)));)由于 HashMap 中没有new Code(123) 新产生对象的地址值,所以返回结果是null。

具体实验过程,你可以用以下语句 覆盖Code类中的hashCode()方法。
        public int hashCode(){
                System.out.println("证¥");
           // return id;
                 return 0;
        }
在hashCode()  和equals(Object anObject)  方法中添加 带有标记的语句 来查看运行结果,帮助你理解。
回复 使用道具 举报
添加 带有标记的  打印语句 来查看运行结果
回复 使用道具 举报
map.put(p1.id,p1);//根据身份证来作为key值存放到Map中

既然你是使用身份证p.id作为HashMap集合的key,所以就应该重写作为key的hashCode()和equals()方法(你不重写,那么将使用继承于Object的hashCode()方法来判断hashCode值),而重写集合的值Person的hashCode()和equals()没有作用的。
回复 使用道具 举报
本帖最后由 H07000223 于 2012-2-25 11:09 编辑

// hashcode 改到这里就正确了
public int hashCode(){
       return id;
}
终于弄明吧你想问什么了:为什么hashCode方法必须重写在Code类中,而不是Person类中,是吧~~~

说说我的看法:
HashMap存储的是键值对,当添加包含相同key的键值对时,后者会覆盖前者
也就是你这里面的new Person("张山",new Code(123))覆盖了,new Person("张三",new Code(123))。
所以在HashMap里面想让自己定义的类型的类,也满足key相同,则覆盖的特性。作为key的对象类型
所在的类必须重写equals和hashCode方法。而作为value的对象类型所在的类没有这方面的需求。
Person你完全可以这样写,一点问题都没有:
class Person {
        Code id;// 身份证
        String name;// 姓名
        public Person(String name, Code id) {
                this.id=id;
                this.name=name;
        }

        public String toString() {
                return "姓名:"+name+" 身份证:"+id.id+"\n";
        }
}
回复 使用道具 举报
本帖最后由 谢明 于 2012-2-25 15:18 编辑
  1.         //package c08.hashEx;
  2.         import java.util.*;
  3.         //身份证类
  4.         class Code{
  5.                 final int id;//身份证号码已经确认,不能改变
  6.                 Code(int i){
  7.                         id=i;

  8.                 }

  9.                 public boolean equals(Object anObject) {
  10.                         if (anObject instanceof Code){
  11.                                 Code other=(Code) anObject;
  12.                                 return this.id==other.id;
  13.                         }
  14.                         return false;
  15.                 }
  16.                 // hashcode 改到这里就正确了
  17.                 public int hashCode(){
  18.                 System.out.println("code调用hashcode");
  19.                 return id;
  20.                 }
  21.                 public String toString() {
  22.                         return "身份证:"+id;
  23.                 }

  24.         }
  25.         //人员信息类
  26.         class Person {
  27.                 Code id;// 身份证
  28.                 String name;// 姓名
  29.                 public Person(String name, Code id) {
  30.                         this.id=id;
  31.                         this.name=name;
  32.                 }

  33.                 public boolean equals(Object anObject) {
  34.                         if (anObject instanceof Person){
  35.                                 Person other=(Person) anObject;
  36.                                 return this.id.equals(other.id);
  37.                         }
  38.                         return false;
  39.                 }

  40.                 //写了2个 标注了下
  41.                 public int hashCode(){
  42.                         System.out.println("person调用hashcode");
  43.                         return id.id;
  44.                 }
  45.                 public String toString() {
  46.                         return "姓名:"+name+" 身份证:"+id.id+"\n";
  47.                         //return "姓名:"+name+"\n";
  48.                 }
  49.         }
  50.         public class HashCodeEx {
  51.                 public static void main(String[] args) {
  52.                         Person p1=new Person("张三",new Code(123));                       
  53.                         Person p2=new Person("李四",new Code(456));                       
  54.                         HashMap map1=new HashMap();
  55.                         System.out.println("---------------------------");
  56.                         map1.put(p1,p1.id);//根据person作为key值存放到Map中

  57.                         map1.put(p2,p2.id);

  58.                         System.out.println("Map1 k:person v:id 信息:\n"+map1);
  59.                         System.out.println("---------------------------");

  60.                         HashMap map2=new HashMap();

  61.                         map2.put(p1.id,p1);//根据身份证来作为key值存放到Map中

  62.                         map2.put(p2.id,p2);

  63.                        
  64.                         System.out.println("Map2 k:id v:person 信息:\n"+map2);
  65.                         System.out.println("---------------------------");
  66.                         // 张三 改名为:张山
  67.                         Person p3=new Person("张山",new Code(123));
  68.                         map1.put(p3,p3.id);
  69.                         System.out.println("张三改名后 Map1 k:person v:id 中存放的人员信息:\n"+map1);
  70.                         System.out.println("---------------------------");
  71.                         map2.put(p3.id,p3);
  72.                         System.out.println("张三改名后 Map2 k:id v:person 中存放的人员信息:\n"+map2);
  73.                         System.out.println("---------------------------");
  74.                         //查找身份证为:123 的人员信息
  75.                         System.out.println("map2查找身份证为:123 的人员信息:"+map2.get(new Code(123)));
  76.                         System.out.println("map1查找person p5     的人员信息:"+map1.get(p3));
  77.                 }
  78.         }
  79. /*
  80. ---------------------------
  81. person调用hashcode
  82. person调用hashcode
  83. Map1 k:person v:id 信息:
  84. {姓名:李四 身份证:456
  85. =身份证:456, 姓名:张三 身份证:123
  86. =身份证:123}
  87. ---------------------------
  88. code调用hashcode
  89. code调用hashcode
  90. Map2 k:id v:person 信息:
  91. {身份证:456=姓名:李四 身份证:456
  92. , 身份证:123=姓名:张三 身份证:123
  93. }
  94. ---------------------------
  95. person调用hashcode
  96. 张三改名后 Map1 k:person v:id 中存放的人员信息:
  97. {姓名:李四 身份证:456
  98. =身份证:456, 姓名:张三 身份证:123
  99. =身份证:123}
  100. ---------------------------
  101. code调用hashcode
  102. 张三改名后 Map2 k:id v:person 中存放的人员信息:
  103. {身份证:456=姓名:李四 身份证:456
  104. , 身份证:123=姓名:张山 身份证:123
  105. }
  106. ---------------------------
  107. code调用hashcode
  108. map2查找身份证为:123 的人员信息:姓名:张山 身份证:1

  109. person调用hashcode
  110. map1查找person p5     的人员信息:身份证:123
  111. */
复制代码
{:soso__10882166114642946631_2:}今天改成了这个样子  明朗多了  感谢大家

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