为什么要重写equals方法和hashcode方法?

前言:记得最开始写代码的时候,仿着别人的代码写,发现别人在一些实体类里面重写了hashCode方法和equals方法,当时只明白了为什么要重写equals方法,但是并不知道为什么也要重写hashCode方法,然而也没有去深究,只是照着写(这里严厉批评一下自己,写代码一定要思考,学而不思则罔啊,少年郎,多学,多做,多思考,多反省,多做笔记)后来又接触了几次hashCode的重写,心里产生了巨大的疑问,究竟为什么要重写equals和hashCode,到底好处是什么,到底为什么这样做。然后就查阅了一些资料,做了一些实践,对为什么要重写这两个方法也有了自己的一点理解,下面就将自己之前的一点笔记一点拙见记录在这里。
一.了解hashcode方法
我们知道hashCode和equals都是Object类的方法,Object类是所有类的超类。
我们查阅Object类的源码,会发现hashcode是一个本地方法

  public native int hashCode();

Object类的hashCode方法的返回值跟对象的内存地址有关,根据内存地址返回一个整数。下面一句话摘自Java API

实际上,由 Object 类定义的 hashCode 方法确实会针对不同的对象返回不同的整数。(这一般是通过将该对象的内部地址转换成一个整数来实现的,但是 JavaTM 编程语言不需要这种实现技巧。) 

我们再看看Java API中对该方法的说明

返回该对象的哈希码值。支持此方法是为了提高哈希表(例如 java.util.Hashtable 提供的哈希表)的性能。 
hashCode 的常规协定是: 

在 Java 应用程序执行期间,在对同一对象多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是将对象进行 equals 比较时所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。 
如果根据 equals(Object) 方法,两个对象是相等的,那么对这两个对象中的每个对象调用 hashCode 方法都必须生成相同的整数结果。 
如果根据 equals(java.lang.Object) 方法,两个对象不相等,那么对这两个对象中的任一对象上调用 hashCode 方法不 要求一定生成不同的整数结果。但是,程序员应该意识到,为不相等的对象生成不同整数结果可以提高哈希表的性能。 

如果根据 equals(Object) 方法,两个对象是相等的,那么对这两个对象中的每个对象调用 hashCode 方法都必须生成相同的整数结果。 所以这里就有一条我们必须在重写equals的时候重写hashCode的佐证了。如果不重写hashCode很难保证equals相等时,hashCode方法的返回值相等。因为不重写hashCode时,调用的是Object类的hashCode方法,返回值和对象内存地址直接相关。就极有可能导致hashCode不同。(其实这个佐证并没有卵用,因为这是通过Java API规定推出来的,其实呀,之所以有这样的规定也是因为下一条原因)。到底为什么一定要重写hashCode呢,当然有更有说服力的原因。

我们注意看API中的一句话:

返回该对象的哈希码值。支持此方法是为了提高哈希表(例如 java.util.Hashtable 提供的哈希表)的性能。

这里提到了哈希表,还涉及到了Hashtable类,不过现在Hashtable类逐渐被HashMap代替。大家都知道HashMap是我们用的非常多的一个集合容器,而HashMap的具体实现是跟hashCode有着非常重要的关系的,这点可以通过翻阅源码得知。我们重写Equals类可以说是站在用户的角度来看,根据具体的逻辑来判断到底怎样两个对象就是相等。而重写hashCode()就是为了提高HashMap等实现中依赖于hashCode值的集合中hash表的性能,提高程序的执行效率。
具体的解释,我会在介绍HashMap的博客中给出。

展开阅读全文

没有更多推荐了,返回首页