我重写的equals方法,但为什么运行结果还有重复的?
package Test_05;
import java.util.HashSet;
import java.util.Iterator;
class Person{
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// 重写hashCode方法,返回name属性的哈希值
public int hashCode(){
return name.hashCode();
}
// 重写equals方法
public boolean equals(Object obj){
if(this.name == obj)
return true;
return false;
}
public String toString(){
return "Person " + name + age;
}
}
public class T5_10 {
public static void main(String[] args) {
// 创建HashSet对象
HashSet hs = new HashSet();
// 将Person对象存入集合
hs.add(new Person("lisa", 21));
hs.add(new Person("lisi", 32));
hs.add(new Person("lisi", 32));
hs.add(new Person("leilei", 31));
hs.add(new Person("lusi", 25));
hs.add(new Person("lusi", 25));
// 遍历集合中的元素
Iterator it = hs.iterator();
while (it.hasNext()) {
Person p = (Person) it.next();
System.out.println(p);
}
}
}
问题出在你重写的equals方法上,17行的 this.name == obj
换成this.name == ((Person) obj).name
就不会有重复值了。
解析:
HashSet底层用的是HashMap中key的存储方式,先看HashMap源码中的put方法关键代码。
源码中判断两个对象是否相等的条件:两个对象的hashCode相等,并且==或者equals判断相等
这里又引申出==与equals的区别。
==比较的是两对象的内存地址,equals是可以由开发者自己定义判断逻辑的比较方法。
你放进HashMap里的Person对象,每一个都有自己独立的地址空间,即内存地址不同
。很明显,==
判定为不同的对象,可以同时放进HashMap中。又因为你重写的equals方法中也是用的==,
导致equals实际上是用Person这个对象的name属性与Person对象比较,当然是判定为不同的对象,即可以同时存在于HashMap中
。
由以上分析得出,将equals中的this.name == obj
换成this.name == ((Person) obj).name
即可解决问题。
实际上这里还涉及到了字符串常量池的问题,有兴趣你可以去百度看看相关博客,我这里展开就太多了。
String更推荐用这种比较形式 this.name.equals(((Person) obj).name)
。
你的name怎么可能会和存入的obj相等那?要比较也是比较name和obj的name