参考与学习:http://www.cnblogs.com/skywang12345/p/3324958.html
http://www.cnblogs.com/dolphin0520/p/3681042.html
旨在通过这篇文章把现在我明白的;未来我可能忘记的以及混淆的,写清楚。
hashCode方法
该方法定义在Object类中,是native方法;
(哦我去)
其他啰嗦的我不想写了;不懂直接去看上面两篇博客;(果然!)
点一:equals与==的关系和区别:
Object类中定义的equals方法,就是使用了==来进行比较的;
==,比较的是对象的内存地址是否相同;(这个记住了啊)
点二:我的疑问点在于:
为什么重写equals方法,一定要重写hashCode方法;
第一篇文章解答了我的疑惑;
当定义的类,比如说不会创建Student类对应的散列表中,例如,没有HashMap<\Student>结构,其实在重写equals方法时,是不需要重写hashcode方法的。
public class Student {
String name;
int age;
public Student(){}
public Student(String name,int age){
this.name=name;
this.age=age;
}
@Override
public boolean equals(Object obj){
if(obj==null) return false;
if(this==obj) return true;
if(this.getClass()!=obj.getClass()) return false;
Student st=(Student)obj;
return this.name==st.name&&this.age==st.age;
}
public static void main(String[] args){
Student s1=new Student("lee",18);
Student s2=new Student("lee",18);
System.out.println(s1.equals(s2));
}
}
这个时候比较这两个对象是否相等,只需要重写了equals方法就可以了。(另外注意一下equals方法怎么重写的)
但如果创建了类对应的散列表,如HashMap<\Student>,则在重写equals方法的同时,要重写hashcode方法;
public class Student {
String name;
int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object obj) {
if (obj == null)
return false;
if (this == obj)
return true;
if (this.getClass() != obj.getClass())
return false;
Student st = (Student) obj;
return this.name == st.name && this.age == st.age;
}
@Override
public String toString(){
return "name:"+this.name+" age:"+this.age;
}
public static void main(String[] args) {
Set<Student> set = new HashSet<Student>();
Student s1 = new Student("lee", 18);
Student s2 = new Student("lee", 18);
set.add(s1);
set.add(s2);
System.out.println(s1.equals(s2));
Iterator it=set.iterator();
while(it.hasNext()){
Student st=(Student)it.next();
System.out.println(st.toString());
}
}
}
运行结果:
true
name:lee age:18
name:lee age:18
发现,经equals比较,两个对象相等;但不允许元素重复的set中却包含了这两个对象。造成这个问题的原因就是因为没有重写hashcode方法;
散列表在存储元素的时候,首先根据对象的hashcode方法获得散列值(基于对象的内存地址);这两个对象明显有不同的内存空间,所以通过hashcode获得的散列值不同;HashSet就会认为这是两个不同的对象,分别存储。
解决:
public class Student {
String name;
int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object obj) {
if (obj == null)
return false;
if (this == obj)
return true;
if (this.getClass() != obj.getClass())
return false;
Student st = (Student) obj;
return this.name == st.name && this.age == st.age;
}
@Override
public String toString(){
return "name:"+this.name+" age:"+this.age;
}
@Override
public int hashCode(){
return name.toUpperCase().hashCode()^age;
}
public static void main(String[] args) {
Set<Student> set = new HashSet<Student>();
Student s1 = new Student("lee", 18);
Student s2 = new Student("lee", 18);
set.add(s1);
set.add(s2);
System.out.println(s1.equals(s2));
Iterator it=set.iterator();
while(it.hasNext()){
Student st=(Student)it.next();
System.out.println(st.toString());
}
}
}
运行结果:
true
name:lee age:18