HashSet之对象hashCode重写问题-->急!急!急!

lilewei2008 2009-07-23 08:48:26


Person 类代码:
package test;

public class Person {
private String name;
private int age;

public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Person() {
super();
}
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;
}

@Override
public boolean equals(Object o) {
if(o==null) return false;
if(o==this) return true;

if(o instanceof Person ){
Person p=(Person)o;
if(p.name.equals(this.name)&&p.age==this.age){
return true;
}else{
return false;
}

}else{

return false;
}

}
@Override
public int hashCode() {
return this.name.hashCode()+age;
}
}

这是测试代码:
package test;

import java.util.HashSet;
import java.util.Set;

public class TestHashSet {

public static void main(String[] args) {

Person p=new Person("llw",23);
Set<Person> persons=new HashSet<Person>();
persons.add(p);

System.out.println("persons.contains(p)--> "+persons.contains(p));
System.out.println("p.hashCode()--> "+p.hashCode());

Person getPerson=null;
Person check=null;

for(Person person:persons){

getPerson=person;
System.out.println("getPerson--> "+getPerson);
check=person;
}
getPerson.setAge(22);
System.out.println("getPerson--> "+getPerson);
System.out.println("after setAge()--> "+getPerson.hashCode());
System.out.println("after setAge() contain --> "+persons.contains(getPerson));
System.out.println("check.hashCode()--> "+check.hashCode());
System.out.println("is check in persons --> "+persons.contains(check));
}



运行结果:

persons.contains(p)--> true
p.hashCode()--> 107278
getPerson--> test.Person@1a30e
getPerson--> test.Person@1a30d
after setAge()--> 107277
after setAge() contain --> false
check.hashCode()--> 107277
is check in persons --> false


本人在一个项目里遇到如下问题,就是输出结果里显示的
为什么从Set取出了元素并对其进行了修改后对象的地址会发生变化,也就是产生了新对象
如果不重写hashCode()和equals() 结果就是正确的
这是为什么呢,哪们朋友帮忙回答一下啊??
...全文
631 25 打赏 收藏 举报
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
lilewei2008 2009-07-23
  • 打赏
  • 举报
回复
请问 Alex_20同志,你运行了吗?
你只是在那里说空话。。。

今天就让你见见鬼
你把我的运行一下,在最后的时候你再把set遍历一下看看,
里面元素的hashCode的修改后的是相同的!!!
chenchuanfeng001 2009-07-23
  • 打赏
  • 举报
回复
首先,你修改对象并没有修改对象的地址或生成新对象。
println()方法调用对象的toString()进行输出。
在Object中toString()定义。

public String toString() {
return getClass().getName() + "@" + Integer.toHexString hashCode());
}


默认的hashCode()返回对象的内存地址,但hashCode已经被你重写了,就不会返回内存地址。
2. HashSet 得contains方法是根据对象的hashCode和equals方法去判定的。
先用hashCode,只有hashCode相同才去用equals方法。
Alex_20 2009-07-23
  • 打赏
  • 举报
回复
你最初把Person放入HashSet的时候,Set维护的散列映射是
107278---p
你修改了数据以后hashCode变成了107277,然后你问HashSet里有没有这个键映射的数据,要是有那就见鬼了。
Alex_20 2009-07-23
  • 打赏
  • 举报
回复
去google上查哈希算法,把哈希算法搞明白再来提问,别再说什么hashCode是一样的。
lilewei2008 2009-07-23
  • 打赏
  • 举报
回复
NO ,在修改了getPerson之后,set 里面的元素的hasCode()和getPerson的hasCode()是一样的...
Alex_20 2009-07-23
  • 打赏
  • 举报
回复
你Set里按照107278去散列的,然后你修改了数据hashCode变成了107277,你用107277去Set里找东西当然没结果了。你把哈希算法搞明白了,你就明白你的问题出在什么地方了。
lilewei2008 2009-07-23
  • 打赏
  • 举报
回复
check.hasCode()和getPerson.hasCode()可是一样的啊。。。
Alex_20 2009-07-23
  • 打赏
  • 举报
回复
public int hashCode() {
return this.name.hashCode();
}

hashCode方法你这样改肯定就对了。当然前提是你不修改name的数据。
Alex_20 2009-07-23
  • 打赏
  • 举报
回复
LZ,你同一个类的实例由于某个数据的修改产生了两个截然不同的hasCode这肯定是不对的。Set集合是按照你hasCode的值进行散列的,你同一个对象前后的散列码不一样肯定返回false。
lilewei2008 2009-07-23
  • 打赏
  • 举报
回复
来人啊。。。。
lilewei2008 2009-07-23
  • 打赏
  • 举报
回复
那为什么执行了setAge()后
persons.contains(getPerson);
成了false呢??
check.hasCode()和getPerson.hasCode()可是一样的啊。。。
这是关键。。。。
leblang 2009-07-23
  • 打赏
  • 举报
回复
hashCode 的变化会引起对象地址的变化
lilewei2008 2009-07-23
  • 打赏
  • 举报
回复
那为什么执行了setAge()后
persons.contains(getPerson);
成了false呢??
check.hasCode()和getPerson.hasCode()可是一样的啊。。。
lh_fengyuzhe 2009-07-23
  • 打赏
  • 举报
回复
对象取地址就是用的hashcode 啊
getClass().getName() + '@' + Integer.toHexString(hashCode())
地址肯定有变化
lilewei2008 2009-07-23
  • 打赏
  • 举报
回复
自己往上抬抬!!
lilewei2008 2009-07-23
  • 打赏
  • 举报
回复

谢谢你的鼓励,我会改的。。。,希望能加上你的好友(我已经向你申请了),以后共同学习交流,
你注册帐号那会我还在初中呢。。。呵呵
Alex_20 2009-07-23
  • 打赏
  • 举报
回复
没关系,LZ,做开发最忌讳的就是心浮气躁,遇到问题别着急,静下心来多想,多尝试。
其实往往最基础的东西才是最复杂的。
多线程简单吧?在jdk1.4的时候一个synchronized关键字就解决同步的问题,可是真正能写出漂亮的多线程程序的程序员有多少?
把功夫用在基础上绝对没错。
lilewei2008 2009-07-23
  • 打赏
  • 举报
回复
惭愧。。。
lilewei2008 2009-07-23
  • 打赏
  • 举报
回复
对不起了 ,Alex 同志,这是我项目里的一个问题,半天没有调出程序来,
心里比较窝火,都怪自己基本功不扎实....
希望你能理解..
再次向你道歉了....
Alex_20 2009-07-23
  • 打赏
  • 举报
回复
你修改了数据后hashCode变化了,你通知了HashSet当前对象的hashCode发生变化要更新映射了吗?你不告诉HashSet,HashSet当然是按照最初的映射去查找,那能找到吗?

居然还问我这程序运行了没有,我2001年就注册的帐号,大哥,不是新来的。
加载更多回复(5)

62,620

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧