Android hashcode() 和 equals()作用详解
equals()详解
Object类中的定义
public boolean equals(Object obj) {
return (this == obj);
}
很明显,equals默认是根据地址值(引用)来比较两对象,而Integer、String等类已经重写了Object类的equals()方法,所以可以进行内容的比较。
equals方法重写原则
- 自反性:x.equals(x)必定返回true
- 对称性:x.equals(y)为true,那么y.equals(x)也为true
- 传递性:x.equals(y)为true,y.equals(z)为true,那么x.equals(z)也为true
- 一致性:x.equals(y)为true,无论调用多少次都为true,所以equals方法不要依赖不可靠的资源 如通过ip地址判断URL的相等性
- x.equals(null)必为false; x.equals(与x不同类型对象),必为false
编写高质量的equals方法步骤
- if(obj == this) return true; 高性能
- instanceof 校验对象类型正确性
- 将参数转型到正确的类型
- 对类中的每一个重要的属性跟目标对象进行校验
- 针对实现验证是否对称,传递和一致
例子
@Override
public boolean equals(Object o) {
//1.引用一样,说明是同一个对象,就没必要执行下面判断
if (this == o) {
return true;
}
//2.校验对象类型正确性,不一样就不用在比较下面的
if (!(o instanceof ApplicationInfo)) {
return false;
}
//3.将参数转型到正确的类型;
ApplicationInfo that = (ApplicationInfo) o;
//对类中的每一个重要的属性跟目标对象进行校验
return title.equals(that.title) &&
intent.getComponent().getClassName().equals(
that.intent.getComponent().getClassName());
}
hashCode()详解
想要明白hashCode的作用,你必须要先知道Java中的集合。Java中的集合(Collection)有两类,一类是List,再有一类是Set。前者集合内的元素是有序的,元素可以重复;后者元素无序,但元素不可重复。这就存在一个问题:要想保证元素不重复,可两个元素是否重复应该依据什么来判断呢?这就用到上面的equals()方法,但是,如果每增加一个元素就检查一次,那么当元素很多时,后添加到集合中的元素比较的次数就非常多了。例如,如果集合中现在已经有1000个元素,那么第1001个元素加入集合时,它就要调用1000次equals方法。这显然会大大降低效率。因此就用到hashCode方法。
hashCode方法返回的就是对象存储的物理地址(实际可能并不是),这样,当集合添加新元素时,先调用这个元素的hashCode方法,就能一下子定位到它应该放置的位置上,如果这个位置上没有元素,它可以直接存储在这个位置上,不用再进行任何比较;但如果这位置上已经有元素,就会调用它的equals与新元素进行比较,相同就不存了,不相同就放置到其他位置上,这样就降低了检索时间,提高效率;
hashCode()规定
- equals()相等的两个对象,hashCode()一定相等
- hashCode()相等的两个对象,equals()不一定相等
例子
//学生类,没有重写equals和hashCode
public class Student {
public int id;
public String name;
public Student(int id,String name){
this.id = id;
this.name = name;
}
}
把对象添加到HashSet
HashSet clazz = new HashSet();
clazz.add(new Student(1,"Tony"));
clazz.add(new Student(2,"Jack"));
clazz.add(new Student(1,"Tony"));
遍历clazz输出结果:
1 : Tony
2 : Jack
1 : Tony
显然hashSet添加了相同的学生,hashCode()比较的是对象地址(引用),所以两个new出来的hasCode是不一样,当然此时equals也是不等的。接下来重写equals和hashcode:
@Override
public boolean equals(Object obj) {
if(this == obj){
return true;
}
if(!(obj instanceof Student)){
return false;
}
Student that = (Student) obj;
return this.id==that.id &&
this.name.equals(that.name);
}
@Override
public int hashCode() {
return id+name.hashCode();
}
输出结果:
1 : Tony
2 : Jack