重写equals()时要重写hashCode()
在重写一个类的equals()的同时,一般要重写hashCode()除非你确认类的对象不会放入HashSet,HashTable,HashMap。
那么为什么要重写hashCode()呢?主要是为了确保hash表里面不会被放入重复的对象,以提高性能。那为什么重写了hashCode()就可以做到这一点呢?下面以一段代码分析。
我们看看输出结果:
看到了吗?呵呵,就是每次在往Set里add(object)时,先调用hashCode(),若hash码与set里面某个object的hash码不相等,则直接放入set;否则调用equals(object),若与set中某个object相等(即hashCode相等,而且equals返回true),则返回,不放入set,否则放入set。
再来看看这样重写hashCode时的结果:
再运行一下,结果如下:
也就是说学号不同(各个object的hashCode不同),直接放入Set,没有执行equals。
总结:重写equals的时候,一般要重写hashCode,并尽量保证不同object的hashCode不同,以提高hash的性能
那么为什么要重写hashCode()呢?主要是为了确保hash表里面不会被放入重复的对象,以提高性能。那为什么重写了hashCode()就可以做到这一点呢?下面以一段代码分析。
- /**Strudent重写了equals和hashCode,这里假设只要学号相等则是同一个对象。
- 先看看hashCode()返回相同的值:0的情况。
- */
- public class Student {
- public Student(String no) {
- this.no = no;
- }
- //永远都返回0
- @Override
- public int hashCode() {
- System.out.println("call hashcode");
- return 0;
- }
- // 这里的equals实现学号相同表示相等
- @Override
- public boolean equals(Object obj) {
- System.out.println("call equals");
- if (this == obj)
- return true;
- if (getClass() != obj.getClass())
- return false;
- Student other = (Student) obj;
- if (no == null) {
- if (other.no != null)
- return false;
- } else if (!no.equals(other.no))
- return false;
- return true;
- }
- // 学号,假设必须唯一
- private String no;
- private String name;
- public String getNo() {
- return no;
- }
- public void setNo(String no) {
- this.no = no;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- }
/**Strudent重写了equals和hashCode,这里假设只要学号相等则是同一个对象。
先看看hashCode()返回相同的值:0的情况。
*/
public class Student {
public Student(String no) {
this.no = no;
}
//永远都返回0
@Override
public int hashCode() {
System.out.println("call hashcode");
return 0;
}
// 这里的equals实现学号相同表示相等
@Override
public boolean equals(Object obj) {
System.out.println("call equals");
if (this == obj)
return true;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (no == null) {
if (other.no != null)
return false;
} else if (!no.equals(other.no))
return false;
return true;
}
// 学号,假设必须唯一
private String no;
private String name;
public String getNo() {
return no;
}
public void setNo(String no) {
this.no = no;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
- public class Main {
- public static void main(String[] args) {
- Set<Student> set = new HashSet<Student>();
- set.add(new Student("1"));
- System.out.println("----------");
- set.add(new Student("2"));
- System.out.println("----------");
- set.add(new Student("3"));
- System.out.println("----------");
- System.out.println(set.size());
- }
- }
public class Main {
public static void main(String[] args) {
Set<Student> set = new HashSet<Student>();
set.add(new Student("1"));
System.out.println("----------");
set.add(new Student("2"));
System.out.println("----------");
set.add(new Student("3"));
System.out.println("----------");
System.out.println(set.size());
}
}
我们看看输出结果:
- call hashcode
- ----------
- call hashcode
- call equals
- ----------
- call hashcode
- call equals
- call equals
- ----------
- 3
call hashcode
----------
call hashcode
call equals
----------
call hashcode
call equals
call equals
----------
3
看到了吗?呵呵,就是每次在往Set里add(object)时,先调用hashCode(),若hash码与set里面某个object的hash码不相等,则直接放入set;否则调用equals(object),若与set中某个object相等(即hashCode相等,而且equals返回true),则返回,不放入set,否则放入set。
再来看看这样重写hashCode时的结果:
- //这里返回学号的hashCode。
- @Override
- public int hashCode() {
- System.out.println("call hashcode");
- return no.hashCode();
- }
//这里返回学号的hashCode。
@Override
public int hashCode() {
System.out.println("call hashcode");
return no.hashCode();
}
再运行一下,结果如下:
- call hashcode
- ----------
- call hashcode
- ----------
- call hashcode
- ----------
- 3
call hashcode
----------
call hashcode
----------
call hashcode
----------
3
也就是说学号不同(各个object的hashCode不同),直接放入Set,没有执行equals。
总结:重写equals的时候,一般要重写hashCode,并尽量保证不同object的hashCode不同,以提高hash的性能