Effective Java 第9条: 覆盖 equals 时总要覆盖 hashCode

在每个覆盖了equals 方法的类中,也必须覆盖 hashCode 方法.
否则违反Object.hashCode 通用规定,从而导致无法结合所有基于散列的集合一起正常运作.

Object.hashCode 约定的内容:

  • 在应用程序执行期间,只要对象的equals方法的比较操作所用到的信息没有被修改,那么多次调用hashCode方法都必须始终如一的返回同一个整数. 同一个程序被多次执行过程中, hashCode返回的整数可以不一致.
  • 如果 x.equals(y) == true 那么要求 x.hashCode() == y.hashCode()
  • 如果 x.equals(y) == false, 没有要求 x.hashCode != y.hashCode, 但是不同对象产生不同的hashCode有利于hash tables 的性能.

一个好的散列函数通常倾向于:为不相等的对象产生不相等的散列码.
简单的hash方法:

    1. int result = 17 (要求非0的整数即可)
    1. 对于对象中的每个关键域f(也就是 equals 中涉及的每个域),
      • 2.1 计算该域的散列码 c:
        - i. boolean 类型: c = (f ? 1:0)
        - ii. byte,char,shot,int类型, c = int(f)
        - iii. longs类型: c = (int)(f ^ (f >> 32))
        - iv. float类型: c = Float.floatToIntBits(f)
        - v. double类型: fb = Double.doubleToLongBits(f), c = (int)(fb ^ ( fb >> 32))
        - vi. 对象引用类型: c = (f = null ? 0: f.hashCode())
        - vii. 数组类型: c = Arrays.hashCode()
        • 2.2 rerult = 31 * result + c (使用奇素数31,防止乘法溢出, 并且 31 * i = (i << 5) - i)
    1. return result
    1. 检查是否满足相等的实例具有相等的散列码.

缓存hashCode,并延迟初始化:

private volatile int hashCode;
// equals 方法比较涉及的三个域: short areaCode, short prefix, short lineNumber
@Override 
public int hashCode() {
    int result = hashCode;
    if (result == null) {
        result = 17;
        result = 31 * result * areaCode;
        result = 31 * result * prefix;
        result = 31 * result * lineNumber;
        hashCode = result;
    }
    return result;
}

**不要试图从散列码计算中排除一个对象的关键部分来提高性能.这样虽然计算hashCode可能会快一点,但是hash表不一定好.

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 2017年12月15日清早,昨晚的梦,一只白花花的肥硕大猫,摇摇晃晃走向躲在阁楼里的人群,大猫扑咬向谁,谁瞬间灰飞...
    宋允儿阅读 293评论 0 0
  • 双11就在眼前,萃花一直在考虑买点什么好,最后还是决定买点钱,要知道纸币也是收藏投资的热门品类。 截止目前我国共发...
    艺萃阅读 427评论 0 0
  • 以前写的小文章。。上一篇很仓促 这是以前为投稿的。那时思维也挺混乱的 详情 感悟生命 ——大二 题记:仿佛一切在奔...
    terryhero阅读 199评论 0 1