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() 结果就是正确的
这是为什么呢,哪们朋友帮忙回答一下啊??
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() 结果就是正确的
这是为什么呢,哪们朋友帮忙回答一下啊??
getClass().getName() + '@' + Integer.toHexString(hashCode())
地址肯定有变化
persons.contains(getPerson);
成了false呢??
check.hasCode()和getPerson.hasCode()可是一样的啊
persons.contains(getPerson);
成了false呢??
check.hasCode()和getPerson.hasCode()可是一样的啊
这是关键。
return this.name.hashCode();
}hashCode方法你这样改肯定就对了。当然前提是你不修改name的数据。
107278---p
你修改了数据以后hashCode变成了107277,然后你问HashSet里有没有这个键映射的数据,要是有那就见鬼了。
println()方法调用对象的toString()进行输出。
在Object中toString()定义。public String toString() {
return getClass().getName() + "@" + Integer.toHexString hashCode());
}
默认的hashCode()返回对象的内存地址,但hashCode已经被你重写了,就不会返回内存地址。
2. HashSet 得contains方法是根据对象的hashCode和equals方法去判定的。
先用hashCode,只有hashCode相同才去用equals方法。
你只是在那里说空话今天就让你见见鬼
你把我的运行一下,在最后的时候你再把set遍历一下看看,
里面元素的hashCode的修改后的是相同的!!!
Person放入HashSet,则hashSet的hash桶里会建立一个映射关系
107278---p
你把person修改以后,hashcode变成了107277,HashSet.contain(person)是怎么来比较的呢?他不是遍历set来比较person和每个元素的hashcode是否相等。那样就不叫hashSet了!!!
具体是这样的,它先获取待比较的元素person的hashcode,现在已经是107277,1在到hash桶里去取107277对应的元素
2然后判断这2个元素的hashcode是否相等并且是否equal.
由于之前的107278---p 对于修改都的元素来说是一个错误的映射,所以在hash桶里根本没有找到存放的这个元素,第2步都没有进行就直接返回false了当equals和hashCode依赖于会变化的状态时,那么就会给用户带来问题。如果这样的对象被放入到集合中,用户必须小心,不要修改这些这些对象所依赖的状态。如果你需要根据对象当前的状态进行比较的话,你应该不要再重定义equals,应该起其他的方法名字而不是equals
你在改之后再去遍历set它的hashCode() 也是107277
请调试 !!
这又怎么样呢?上面已经说了,contain方法又不是遍历去比较的,问题的关键是他无法根据107277在hash桶里找到这个元素
心里比较窝火,都怪自己基本功不扎实....
希望你能理解..
再次向你道歉了....
其实往往最基础的东西才是最复杂的。
多线程简单吧?在jdk1.4的时候一个synchronized关键字就解决同步的问题,可是真正能写出漂亮的多线程程序的程序员有多少?
把功夫用在基础上绝对没错。