Effective Java 覆盖equals时总要覆盖hashCode

一. Object.hashCode通用约定
1. 在应用程序执行期间,只要对象的equals方法的比较操作所用到的信息没有被修改,那么对这同一个对象调用多次,hashCode方法都必须始终如一地返回同一个整数. 在同一个应用程序的多次执行过程中,每次执行所返回的整数可以不一致

   2. 如果两个对象根据equals(Object)方法比较是想等的,那么调用两个对象总任意一个对象的hashCode方法都必须产生同样的整数结果

  3. 如果两个对象根据equals(Object)方法比较是不想等的,那么调用这两个对象中的任意一个对象的hashCOde方法,则不一定要产生不同的整数结果. 但是程序员应该知道,给不同的对象产生截然不同的整数结果,有可能提高hash table 的性能

二. 不覆盖hashCode的错误
由第一部分知,没有覆盖hashCode违反了第二条约定: 想等对象必须具有想等的hashCode,两个对象逻辑上相等,但根据Object的Hash方法,他们是不同的,这样达不到第二条的额效果

三.实现hash方法时,减少冲突的解决方式
一个好的hash算法的理想结果应该是: 为不同的对象产生不相等的hash code,使不相等的实例均匀地分布到所有可能的hash code中:

 1. 把某个非零的常数值保存到名为result的int类型的变量中.

 2. 对于对象中的每个关键域f(equals方法中涉及的每个域),完成以下步骤:

      A. 为该域计算int类型的hash code C

           a. 该域是boolean类型                  计算(f?1:0)
           b. 该域是byte、char、short、int类型    计算(int)f
           c. 该域是long类型                     计算(int)(f^(f>>>32))
           d. 该域是float类型                    计算Float.floatToIntBits(f)
           e. 该域是double类型                   计算Double.doubleToLongBits(f),然后按步骤c计算
           f. 如果该域是一个对象的引用,并且该类的equals方法通过递归地调用equals的方式来比较这个域,则同样为这个域递 归地调用hashCode。
          g. 如果该域是一个数组,则要把每个元素当做单独的域来处理。也就是说,递归地应用上述规则,对每个重要的元素计算一个散列码,然后根据步骤3中的做法把这些散列值组合起来。如果数组域中的每个元素都很重要,可以利用发行版本1.5中增加的其中一个Arrays.hashCode方法

        B. 按照下列公式,把步骤2.a中计算结果hash code C合并到result中:

                 result = 31* result + c;

  3. 返回result

  4. 测试

四: 不要试图从hash code计算中排除掉一个对象的关键部分来提高性能
这么做可能导致hash table完全无法使用,在忽略的区域,实例之间的区别依然很大,可能会造成比较大的hash冲突,甚至退化成链表.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值