Effective Java笔记(11)覆盖 equals 时总要覆盖 hashCode

        在每个 覆盖了 equals 方法的类中,都 必须 覆盖 hashCode 方法 。 如果不这样做的话,就会违反 hashCode 的通用约定,从而导致该类无法结合所有基于散列的集合一起正常运作,这类集合包括 HashMap 和 HashSet 。 下面是约定的内容,摘自 Object 规范:

  • 1、在应用程序的执行期间,只要对象的 equals 方法的比较操作所用到的信息没有被修改,那么对同一个对象的多次调用,hashCode 方法都必须始终返回同一个值 。在一个应用程序与另一个程序的执行过程中,执行 hashCode 方法所返回的值可以不一致 。
  • 2、如果两个对象根据 equals(Object )方法比较是相等的,那么调用这两个对象中的 hashCode 方法都必须产生同样的整数结果 。
  • 3、如果两个对象根据 equals(Object )方法比较是不相等的,那么调用这两个对象中的 hashCode 方法,则不一定要求 hashCode 方法必须产生不同的结果 。 但是程序员应该知道,给不相等的对象产生截然不同的整数结果,有可能提高散列表( hash table )的性能 。

        因没有覆盖 hashCode 而违反的关键约定是 第二条:相等的对象必须具有相等的散到码( hash code ) 。 根据类的 equals 方法,两个截然不同的实例在逻辑上有可能是相等的,但是根据 Object 类的 hashCode 方法,它们仅仅是两个没有任何共同之处的对象 。因此,对象的 hashCode 方法返回两个看起来是随机的整数,而不是根据第二个约定所要求的那样,返回两个相等的整数 。

        不要试图从散列 码计算 中排 除掉一个对 象 的 关键域来提高性能 。 虽然这样得到的散列函数运行起来可能更快,但是它的效果不见得会好,可能会导致散列表慢到根本无法使用 。特别是在实践中,散列函数可能面临大量的实例,在你选择忽略的区域之中,这些实例仍然区别非常大 。 如果是这样,散列函数就会把所有这些实例映射到极少数的散列码上,原本应该以线性级时间运行的程序,将会以平方级的时间运行 。

        不要对 hash Code 方法的返回值做出具体的规定,因此客户端无法理所当然地依赖它;这样可以为修改提供灵活性 。Java 类库中的许多类,比如 String 和 Integer ,都可以把它们的 hashCode 方法返回的确切值规定为该实例值的一个函数。一般来说,这并不是个好主意,因为这样做严格地限制了在未来的版本中改进散列函数的能力 。 如果没有规定散列函数的细节,那么当你发现了它的内部缺陷时,或者发现了更好的散列函数时·,就可以在后面的发行版本中修正它 。

        总而言之,每当覆盖 equals 方法时都必须覆盖 hashCode ,否则程序将无法正确运行 。
hashCode 方法必须遵守 Object 规定的通用约定,并且必须完成一定的工作,将不相等的散列码分配给不相等的实例 。 

你可能感兴趣的:(Effective,Java,java,开发语言,后端)