hashCode与equals

平时我们在项目里经常会用到HashMap这个数据结构,所以在面试的时候一定会被问这个问题∶你有没有重写过hashCode方法?你在使用HashMap时有没有重写hashCode和equals方法?你是怎么写的? 那么为什么要重写hashCode与equals方法,这两个方法起着什么作用呢?当我们往HashMap里放key时,首先会调用这个对象的hashCode方法计算它的hash值,随后把key放入hash值所指引的内存位置。

equals()方法

equals是超类Object中的一个基本方法,是用来判断一个对象和另一个对象是否具有相同的引用(即内存地址),如果有则返回true,下面是Object类的equals()方法:

1public boolean equals(Object obj) {
2    return (this == obj);
3}

equals()与 == 的区别

对于从Object继承而来的equlas方法,与 == 并无区别,都是比较的对象的内存地址。但是我们可以重写equals方法,使其按照我们的要求来进行比较。比如String类就重写了equals方法,比较的是字符串的字符序列,而不是内存地址。

equals()的重写规则

  • 自反性:对于任何非null的引用值x,x.equals(x)应该返回true
  • 对称性:对于任何非null的引用值x与y,当且仅当:y.equals(x)返回true时,x.equals(y)才返回true
  • 传递性:对于任何非null的引用值x、 y与z,如果y.equals(x)返回true,y.equals(z)返回true,那么x.equals(z)也应该返回true
  • 一致性:对于任何非null的引用值x与y,假设对象的equals比较中的信息没有被修改,则多次调用x.equals(y)始终返回true或者始终返回false
  • 对于任何非null的引用值x,x.equals(null)应返回false

上述这些规则在同一个类的两个对象中还是很容易理解的。

hashCode()方法

hash code是一种通过对象得出Hash值的方式,在Java中,每个对象都会有一个对应的hashCode。通过算法,算出对象的hashcode,同一个对象的hashcode唯一(前提是对象没有被改变),但是不同的对象也可能有相同的hashCode。

HashMap

**HashMap通过计算对象的Hash值判断对象应该在Hash表的哪个链上,通过equals方法判断是否是同一个对象。**关键是我们没有重写hashCode方法,调用的仍是Object类的hashCode方法(因为所有的类都是Object的子类),而Object类的hashCode方法返回的hash值其实可以看出是对象的内存地址。

因为在hashMap中,判断key是否相等首先是比较hashCode,然后再用equals比较。我们重写equals方法是为了按我们自己的想法来比较两个对象是否相等。如果不重写hashCode方法,可能出现具有相同含义的不同对象(他们的hashCode不同)被pass掉的情况。而实际上他们应该是相同的key。而如果只重写hashCode不重写equals方法,那么equals只是判断两个对象是否是同一个对象。所以需要同时重写equals和hashCode方法,目的是为了准确定位到我们期望的key。