原创文章,转载请注明原文章地址,谢谢!
首先,equals()方法和hashCode()方法都是Object类中的方法,用来比较两个对象是否相等。那么在讲equals()方法和hashCode()方法之前,先来看一下等于号==的作用。
==
在Java中,如果是基本类型的数据,==比较的是两个数据的值是否相等,如果是引用类型的数据,那么==比较的是两个数据的引用是否相等。
public class Test {
public static void main(String[] args) {
Integer i1 = 1;
Integer i2 = 1;
System.out.println(i1 == i2);//true
Integer i3 = new Integer(11);
Integer i4 = new Integer(11);
System.out.println(i3 == i4);//false
}
}
equals()方法
Object类中的equals()默认等同于==,大多数时候,我们创建的都是引用对象,所以需要在对象中重写equals()方法。
public class Test {
public static void main(String[] args) {
Integer i1 = 1;
Integer i2 = 1;
System.out.println(i1.equals(i2));//true
Integer i3 = new Integer(11);
Integer i4 = new Integer(11);
System.out.println(i3.equals(i4));//true
Object o1 = new Object();
Object o2 = new Object();
System.out.println(o1.equals(o2));//false
}
}
上述o1和o2比较是false,但是我们如果需要比较两个对象是否相等,通常两个对象像上述这种,应该要相等,那么就要求在对象中重写equals()方法,重写比较的逻辑。如果对象中不重写equals()方法,那么默认使用父类的equals()方法比较,一直到Object类。再比如String类中的equals()方法:
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String) anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
下面举一个实际应用的例子,创建一个学生类,然后在测试中测试equals()方法。
@Data
public class Student {
//学号
private String sn;
//学生姓名
private String name;
//学生年龄
private Integer age;
@Override
public boolean equals(Object obj) {
if (obj == null || !(obj instanceof Student)) {
return false;
}
if (((Student) obj).getSn() == this.getSn()) {
return true;
}
return false;
}
}
我们假设如果学生类中学号相同的,就认为是同一个学生,那么测试一下
public class Test {
public static void main(String[] args) {
Student student1 = new Student();
student1.setSn("001");
student1.setName("张无忌");
Student student2 = new Student();
student2.setSn("001");
student2.setName("阿牛");
System.out.println(student1.equals(student2));//true
}
}
观察结果返回true,实际上是得到了我们想要的结果,那么既然如此,为何还要重写hashCode()方法呢?
hashCode()方法
hashCode是jdk根据对象的地址或者字符串或者数字算出来的int类型的数值。在Object类中的定义是public native int hashCode(),用于返回该对象的哈希码值。此方法是为了提高哈希表的性能。
- hashCode的一致性:在Java应用程序执行期间,在对同一对象多次调用hashCode方法时,必须一致地返回相同的整数,前提是将对象进行hashcode比较时所用的信息没有被修改。
- 如果根据equals(Object)方法,两个对象是相等的,那么对这两个对象中的每个对象调用hashCode方法都必须生成相同的整数结果。
- 如果根据equals(java.lang.Object)方法,两个对象不相等,那么对这两个对象中的任一对象上调用hashCode方法不一定生成不同的整数结果。但是,程序员应该意识到,为不相等的对象生成不同整数结果可以提高哈希表的性能。
根据上面的equals()方法的例子和关于和hashCode()方法的比较,我们知道比较两个对象是否相等的条件就是看这两个对象的equals()方法是否相等,那么既然如此,为何要说,在重写equals()方法的同时也必须重写hashCode()方法?
其实这一点关乎哈希表的性能方面。举个例子,在Java的集合中,比如Map或者Set,其中存放的对象是唯一的,不能重复,当要往集合中新增一个对象时,那肯定要判断当前集合中有没有该对象。假如没有hashCode,那么就是遍历,一个个的用equals()方法进行比较,那么数据量大的时候,这种做法是很伤效率的。如果有hashCode,那么我们在一开始往集合中添加对象的时候,先会计算出该对象的哈希码值,然后根据哈希算法计算出该对象存储的位置,那么下次往该集合中新增对象的时候,只需要判断需要添加的位置上是否有对象即可。
总结
- 重写hashCode()方法,主要也是因为考虑哈希表的性能,这点在集合框架中有广泛应用。
- 在集合中,要判断两个对象是否相等,首先判断它们的equals(),如果相等,再去判断hashCode()的返回值,如果都返回true,则认为这两个对象相等。
- 拿集合类来说,由于Object类中的hashCode()返回的是对象的hash值,所以即使equals返回true,集合也可能判定两个对象不等,所以必须重写hashCode()方法,以保证当equals()返回true时,hashCode()也返回true,这样才能使得集合中存放的对象唯一。
博客内容仅供自已学习以及学习过程的记录,如有侵权,请联系我删除,谢谢!
网友评论