美文网首页
Java中的equals()方法和hashCode()方法

Java中的equals()方法和hashCode()方法

作者: 因你而在_caiyq | 来源:发表于2019-04-16 20:01 被阅读0次

原创文章,转载请注明原文章地址,谢谢!

首先,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,这样才能使得集合中存放的对象唯一。

博客内容仅供自已学习以及学习过程的记录,如有侵权,请联系我删除,谢谢!

相关文章

网友评论

      本文标题:Java中的equals()方法和hashCode()方法

      本文链接:https://www.haomeiwen.com/subject/pzabwqtx.html