黑马程序员技术交流社区
标题:
hashmap问题 求解
[打印本页]
作者:
谢明
时间:
2012-2-25 02:15
标题:
hashmap问题 求解
//package c08.hashEx;
import java.util.*;
//身份证类
class Code{
final int id;//身份证号码已经确认,不能改变
Code(int i){
id=i;
}
public boolean equals(Object anObject) {
if (anObject instanceof Code){
Code other=(Code) anObject;
return this.id==other.id;
}
return false;
}
// hashcode 改到这里就正确了
//public int hashCode(){
//return id;
//}
public String toString() {
return "身份证:"+id;
}
}
//人员信息类
class Person {
Code id;// 身份证
String name;// 姓名
public Person(String name, Code id) {
this.id=id;
this.name=name;
}
public boolean equals(Object anObject) {
if (anObject instanceof Person){
Person other=(Person) anObject;
return this.id.equals(other.id);
}
return false;
}
public int hashCode(){
return id.id;
}
public String toString() {
return "姓名:"+name+" 身份证:"+id.id+"\n";
}
}
public class HashCodeEx {
public static void main(String[] args) {
HashMap map=new HashMap();
Person p1=new Person("张三",new Code(123));
map.put(p1.id,p1);//根据身份证来作为key值存放到Map中
Person p2=new Person("李四",new Code(456));
map.put(p2.id,p2);
Person p3=new Person("王二",new Code(789));
map.put(p3.id,p3);
System.out.println("HashMap 中存放的人员信息:\n"+map);
// 张三 改名为:张山 但是还是同一个人。
Person p4=new Person("张山",new Code(123));
map.put(p4.id,p4);
System.out.println("张三改名后 HashMap 中存放的人员信息:\n"+map);
//查找身份证为:123 的人员信息
System.out.println("查找身份证为:123 的人员信息:"+map.get(new Code(123)));
}
}
复制代码
为什么我的hashcode 写到 person 里面就不行了呢 不能判断
作者:
tanlei200620
时间:
2012-2-25 03:27
首先理清下思路:
你是想通过 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) 方法中添加 带有标记的语句 来查看运行结果,帮助你理解。
作者:
tanlei200620
时间:
2012-2-25 03:33
添加 带有标记的
打印语句
来查看运行结果
作者:
刘基军
时间:
2012-2-25 09:56
map.put(p1.id,p1);//根据身份证来作为key值存放到Map中
既然你是使用身份证p.id作为HashMap集合的key,所以就应该重写作为key的hashCode()和equals()方法(你不重写,那么将使用继承于Object的hashCode()方法来判断hashCode值),而重写集合的值Person的hashCode()和equals()没有作用的。
作者:
H07000223
时间:
2012-2-25 10:58
本帖最后由 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:16
本帖最后由 谢明 于 2012-2-25 15:18 编辑
//package c08.hashEx;
import java.util.*;
//身份证类
class Code{
final int id;//身份证号码已经确认,不能改变
Code(int i){
id=i;
}
public boolean equals(Object anObject) {
if (anObject instanceof Code){
Code other=(Code) anObject;
return this.id==other.id;
}
return false;
}
// hashcode 改到这里就正确了
public int hashCode(){
System.out.println("code调用hashcode");
return id;
}
public String toString() {
return "身份证:"+id;
}
}
//人员信息类
class Person {
Code id;// 身份证
String name;// 姓名
public Person(String name, Code id) {
this.id=id;
this.name=name;
}
public boolean equals(Object anObject) {
if (anObject instanceof Person){
Person other=(Person) anObject;
return this.id.equals(other.id);
}
return false;
}
//写了2个 标注了下
public int hashCode(){
System.out.println("person调用hashcode");
return id.id;
}
public String toString() {
return "姓名:"+name+" 身份证:"+id.id+"\n";
//return "姓名:"+name+"\n";
}
}
public class HashCodeEx {
public static void main(String[] args) {
Person p1=new Person("张三",new Code(123));
Person p2=new Person("李四",new Code(456));
HashMap map1=new HashMap();
System.out.println("---------------------------");
map1.put(p1,p1.id);//根据person作为key值存放到Map中
map1.put(p2,p2.id);
System.out.println("Map1 k:person v:id 信息:\n"+map1);
System.out.println("---------------------------");
HashMap map2=new HashMap();
map2.put(p1.id,p1);//根据身份证来作为key值存放到Map中
map2.put(p2.id,p2);
System.out.println("Map2 k:id v:person 信息:\n"+map2);
System.out.println("---------------------------");
// 张三 改名为:张山
Person p3=new Person("张山",new Code(123));
map1.put(p3,p3.id);
System.out.println("张三改名后 Map1 k:person v:id 中存放的人员信息:\n"+map1);
System.out.println("---------------------------");
map2.put(p3.id,p3);
System.out.println("张三改名后 Map2 k:id v:person 中存放的人员信息:\n"+map2);
System.out.println("---------------------------");
//查找身份证为:123 的人员信息
System.out.println("map2查找身份证为:123 的人员信息:"+map2.get(new Code(123)));
System.out.println("map1查找person p5 的人员信息:"+map1.get(p3));
}
}
/*
---------------------------
person调用hashcode
person调用hashcode
Map1 k:person v:id 信息:
{姓名:李四 身份证:456
=身份证:456, 姓名:张三 身份证:123
=身份证:123}
---------------------------
code调用hashcode
code调用hashcode
Map2 k:id v:person 信息:
{身份证:456=姓名:李四 身份证:456
, 身份证:123=姓名:张三 身份证:123
}
---------------------------
person调用hashcode
张三改名后 Map1 k:person v:id 中存放的人员信息:
{姓名:李四 身份证:456
=身份证:456, 姓名:张三 身份证:123
=身份证:123}
---------------------------
code调用hashcode
张三改名后 Map2 k:id v:person 中存放的人员信息:
{身份证:456=姓名:李四 身份证:456
, 身份证:123=姓名:张山 身份证:123
}
---------------------------
code调用hashcode
map2查找身份证为:123 的人员信息:姓名:张山 身份证:1
person调用hashcode
map1查找person p5 的人员信息:身份证:123
*/
复制代码
{:soso__10882166114642946631_2:}今天改成了这个样子 明朗多了 感谢大家
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2